mirror of
https://github.com/PerpetualSoftware/pad.git
synced 2026-09-20 17:43:26 +00:00
756d91acad
CI on main has been failing since the PLAN-866 attachment work
landed. Two independent issues:
1. gofmt failures (golangci-lint) — seven files in the attachments
path had trailing-comment alignment that gofmt wanted nudged a
column. Pure whitespace; ran `gofmt -w` across the affected
files. golangci-lint's gofmt linter caught it on every PR /
push since TASK-870 but we hadn't been watching those signals.
Files cleaned: internal/attachments/{fs_store_test,mime,
mime_test,processor_test}.go, internal/server/{
handlers_attachments_download_test,handlers_attachments_transform,
render/attachments_test}.go.
Local guard: `gofmt -l ./...` now exits clean.
2. Race-detector tests timed out at 20m on the GitHub-hosted runner.
Two contributors:
- PostgreSQL adds latency on every CREATE/DROP plus on the
bcrypt hash inside auth/bootstrap (~3s per call under -race
on the runner). Tests that bootstrap a fresh user (e.g.
TestSessionIPChange_*) pay the full cost each time.
- The PLAN-866 image-processing tests (thumbnail derivation,
rotate / crop transform) added ~2-3 minutes of decode/encode
work on top of the existing suite.
The previous "20m gives margin without papering over a hang"
comment was right at the time it was written; we now genuinely
need more headroom. Bumped to 30m on both the SQLite and
PostgreSQL race steps. Genuine deadlocks would still trip this
and produce the goroutine-dump panic — we just stop confusing
"slow but progressing" with "permanently hung".
Reference points before / after:
- TASK-875 main run #294: Go (PostgreSQL) finished in 17m48s ✓
- TASK-880 main run #298: Go (PostgreSQL) hit 20m timeout ✗
- Local: my new tests under -race add ~63s on a developer laptop
(TestThumbnails + TestTransform + TestProcessor combined).
Verification:
go test ./... — pass
go vet ./... — clean
gofmt -l (recursively) — clean
216 lines
7.5 KiB
YAML
216 lines
7.5 KiB
YAML
name: CI
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
pull_request:
|
|
branches: [main]
|
|
|
|
concurrency:
|
|
group: ci-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
# All third-party Actions are pinned to a 40-char commit SHA with a trailing
|
|
# '# vX.Y.Z' comment so a compromised maintainer or moved tag cannot silently
|
|
# execute attacker code in CI. Bump the SHA + comment together when updating.
|
|
|
|
jobs:
|
|
go:
|
|
name: Go
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
|
|
|
|
- uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0
|
|
with:
|
|
go-version: "1.26"
|
|
|
|
- name: Create web build placeholder for embed
|
|
run: mkdir -p web/build && echo "placeholder" > web/build/.gitkeep
|
|
|
|
- name: Run go vet
|
|
run: go vet ./...
|
|
|
|
- name: Run golangci-lint
|
|
# only-new-issues: false means CI fails on ANY linter finding,
|
|
# not just findings on PR-changed lines. The IDEA-732 cleanup
|
|
# (PRs #247/#249/#251/#252) cleared the existing findings under
|
|
# the configured linter set in .golangci.yml — staticcheck SA*,
|
|
# govet, ineffassign, gofmt, and the standalone `unused` linter
|
|
# (which reports U1000). Flipping the gate now prevents
|
|
# regression drift going forward.
|
|
# v2 of golangci-lint is required because v1 is capped at older
|
|
# Go releases that we no longer support.
|
|
uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 # v9.2.0
|
|
with:
|
|
version: v2.11.4
|
|
args: --timeout=5m
|
|
only-new-issues: false
|
|
|
|
- name: Run govulncheck
|
|
# Fails the build on any known vulnerability in a package we
|
|
# actually reach via the call graph. Net-positive: catches CVEs
|
|
# in indirect deps early, without the noise of hitting every
|
|
# stale entry in our dependency tree.
|
|
#
|
|
# Pinned to a specific govulncheck release. Track upstream in
|
|
# Pad's workspace; bump intentionally so an upstream behavior
|
|
# change can't break unrelated PRs. Update via:
|
|
# go install golang.org/x/vuln/cmd/govulncheck@<new-tag>
|
|
run: |
|
|
go install golang.org/x/vuln/cmd/govulncheck@v1.2.0
|
|
"$(go env GOPATH)/bin/govulncheck" ./...
|
|
|
|
- name: Run tests
|
|
run: go test ./...
|
|
|
|
- name: Run tests with race detector
|
|
if: github.ref == 'refs/heads/main'
|
|
# Default 10m is tight: the full server-package suite under -race
|
|
# measures ~13m locally on a developer laptop after BUG-851 (the
|
|
# ipRateLimiter goroutine drain). The PLAN-866 attachment work
|
|
# (image decode/encode/resize across thumbnail + transform tests)
|
|
# pushes total race-step runtime past 20m on the GitHub-hosted
|
|
# runner — bumped to 30m to give headroom without papering over
|
|
# an actual hang. Genuine deadlocks would still hit this and
|
|
# produce the goroutine-dump panic.
|
|
run: go test -race -timeout=30m ./...
|
|
|
|
- name: Build binary
|
|
run: go build -o pad ./cmd/pad
|
|
|
|
- name: Verify binary runs
|
|
run: ./pad --help
|
|
|
|
go-postgres:
|
|
name: Go (PostgreSQL)
|
|
runs-on: ubuntu-latest
|
|
services:
|
|
postgres:
|
|
image: postgres:17-alpine
|
|
env:
|
|
POSTGRES_USER: pad
|
|
POSTGRES_PASSWORD: pad
|
|
POSTGRES_DB: pad
|
|
ports:
|
|
- 5432:5432
|
|
options: >-
|
|
--health-cmd "pg_isready -U pad"
|
|
--health-interval 5s
|
|
--health-timeout 3s
|
|
--health-retries 10
|
|
steps:
|
|
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
|
|
|
|
- uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0
|
|
with:
|
|
go-version: "1.26"
|
|
|
|
- name: Create web build placeholder for embed
|
|
run: mkdir -p web/build && echo "placeholder" > web/build/.gitkeep
|
|
|
|
- name: Run tests against PostgreSQL
|
|
env:
|
|
PAD_TEST_POSTGRES_URL: "postgres://pad:pad@localhost:5432/pad?sslmode=disable"
|
|
run: go test ./... -count=1
|
|
|
|
- name: Run tests with race detector against PostgreSQL
|
|
if: github.ref == 'refs/heads/main'
|
|
env:
|
|
PAD_TEST_POSTGRES_URL: "postgres://pad:pad@localhost:5432/pad?sslmode=disable"
|
|
# See SQLite race-detector step: 30m headroom over the default 10m.
|
|
# PostgreSQL adds latency on every CREATE/DROP and bcrypt under
|
|
# -race is ~3s per call — TestSessionIPChange-style tests that
|
|
# bootstrap a fresh user pay the full cost each time. The PLAN-866
|
|
# attachment work pushed the cumulative wall over 20m.
|
|
run: go test -race -timeout=30m ./... -count=1
|
|
|
|
web:
|
|
name: Web
|
|
runs-on: ubuntu-latest
|
|
defaults:
|
|
run:
|
|
working-directory: web
|
|
steps:
|
|
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
|
|
|
|
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
|
with:
|
|
node-version: "22"
|
|
cache: "npm"
|
|
cache-dependency-path: web/package-lock.json
|
|
|
|
- name: Install dependencies
|
|
run: npm ci
|
|
|
|
- name: Audit npm dependencies (production, high+)
|
|
# Fail the build on any HIGH or CRITICAL advisory in production deps.
|
|
# Dev-only advisories are treated as informational — they don't ship
|
|
# and fixing them can require waiting on upstream maintainers.
|
|
run: npm audit --audit-level=high --omit=dev
|
|
|
|
- name: Build
|
|
run: npm run build
|
|
|
|
- name: Type check (svelte-check)
|
|
run: npm run check
|
|
|
|
e2e:
|
|
name: E2E (Playwright)
|
|
runs-on: ubuntu-latest
|
|
# Build the binary + UI once and reuse across Playwright projects.
|
|
# The suite is small (<10s at the time of writing — see TASK-733 for
|
|
# follow-up coverage); the `timeout-minutes` cap is a sanity check.
|
|
timeout-minutes: 10
|
|
steps:
|
|
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
|
|
|
|
- uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0
|
|
with:
|
|
go-version: "1.26"
|
|
|
|
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
|
with:
|
|
node-version: "22"
|
|
cache: "npm"
|
|
cache-dependency-path: web/package-lock.json
|
|
|
|
- name: Install web dependencies
|
|
working-directory: web
|
|
run: npm ci
|
|
|
|
- name: Build web UI
|
|
working-directory: web
|
|
run: npm run build
|
|
|
|
- name: Build pad binary
|
|
# Web build output is embedded via //go:embed; it must exist before
|
|
# the Go build. The CI `go` job above builds against a placeholder,
|
|
# which is fine for tests — for e2e we need the real embedded UI.
|
|
run: go build -o pad ./cmd/pad
|
|
|
|
- name: Install Playwright browsers
|
|
working-directory: web
|
|
# --with-deps pulls in the Ubuntu libraries Playwright needs
|
|
# (libatk, libnss, libcups, …). Scoped to chromium to cut download
|
|
# time — the suite's mobile project uses Pixel 7, which defaults to
|
|
# Chromium, so we don't need WebKit.
|
|
run: npx playwright install --with-deps chromium
|
|
|
|
- name: Run Playwright
|
|
working-directory: web
|
|
env:
|
|
CI: "1"
|
|
run: npx playwright test
|
|
|
|
- name: Upload Playwright report on failure
|
|
if: failure()
|
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
|
with:
|
|
name: playwright-report
|
|
path: web/playwright-report/
|
|
retention-days: 14
|