mirror of
https://github.com/PerpetualSoftware/pad.git
synced 2026-09-10 23:15:40 +00:00
86772b5e9e
Bumps the actions-minor-and-patch group with 6 updates in the / directory: | Package | From | To | | --- | --- | --- | | [actions/setup-go](https://github.com/actions/setup-go) | `6.4.0` | `6.5.0` | | [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) | `9.2.0` | `9.3.0` | | [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) | `4.0.0` | `4.2.0` | | [docker/login-action](https://github.com/docker/login-action) | `4.1.0` | `4.4.0` | | [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) | `7.2.1` | `7.2.3` | | [actions/attest-build-provenance](https://github.com/actions/attest-build-provenance) | `4.1.0` | `4.1.1` | Updates `actions/setup-go` from 6.4.0 to 6.5.0 - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/4a3601121dd01d1626a1e23e37211e3254c1c06c...924ae3a1cded613372ab5595356fb5720e22ba16) Updates `golangci/golangci-lint-action` from 9.2.0 to 9.3.0 - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/1e7e51e771db61008b38414a730f564565cf7c20...ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a) Updates `docker/setup-buildx-action` from 4.0.0 to 4.2.0 - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](https://github.com/docker/setup-buildx-action/compare/4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd...bb05f3f5519dd87d3ba754cc423b652a5edd6d2c) Updates `docker/login-action` from 4.1.0 to 4.4.0 - [Release notes](https://github.com/docker/login-action/releases) - [Commits](https://github.com/docker/login-action/compare/4907a6ddec9925e35a0a9e82d7399ccc52663121...af1e73f918a031802d376d3c8bbc3fe56130a9b0) Updates `goreleaser/goreleaser-action` from 7.2.1 to 7.2.3 - [Release notes](https://github.com/goreleaser/goreleaser-action/releases) - [Commits](https://github.com/goreleaser/goreleaser-action/compare/1a80836c5c9d9e5755a25cb59ec6f45a3b5f41a8...f06c13b6b1a9625abc9e6e439d9c05a8f2190e94) Updates `actions/attest-build-provenance` from 4.1.0 to 4.1.1 - [Release notes](https://github.com/actions/attest-build-provenance/releases) - [Changelog](https://github.com/actions/attest-build-provenance/blob/main/RELEASE.md) - [Commits](https://github.com/actions/attest-build-provenance/compare/a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32...0f67c3f4856b2e3261c31976d6725780e5e4c373) --- updated-dependencies: - dependency-name: actions/attest-build-provenance dependency-version: 4.1.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions-minor-and-patch - dependency-name: actions/setup-go dependency-version: 6.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions-minor-and-patch - dependency-name: docker/login-action dependency-version: 4.2.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions-minor-and-patch - dependency-name: docker/setup-buildx-action dependency-version: 4.1.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions-minor-and-patch - dependency-name: golangci/golangci-lint-action dependency-version: 9.2.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions-minor-and-patch - dependency-name: goreleaser/goreleaser-action dependency-version: 7.2.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions-minor-and-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
392 lines
16 KiB
YAML
392 lines
16 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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
|
|
- uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
|
|
with:
|
|
go-version: "1.26"
|
|
|
|
- name: Allow Go to fetch the toolchain go.mod pins
|
|
# actions/setup-go unconditionally exports GOTOOLCHAIN=local, which
|
|
# forbids Go from fetching the toolchain go.mod requires. go.mod pins
|
|
# `go 1.26.5`, but setup-go's "1.26" resolves to the newest patch in
|
|
# its manifest (1.26.4 here), so every `go` command fails with
|
|
# "go.mod requires go >= 1.26.5 (running go 1.26.4)". Written AFTER
|
|
# setup-go so it wins the $GITHUB_ENV last-write; `auto` lets Go pull
|
|
# 1.26.5 on demand. Added after #896 raised the go.mod floor.
|
|
run: echo "GOTOOLCHAIN=auto" >> "$GITHUB_ENV"
|
|
|
|
- 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@ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a # v9.3.0
|
|
with:
|
|
version: v2.11.4
|
|
args: --timeout=5m
|
|
only-new-issues: false
|
|
# Cap the blast radius of a stale-cache event to ~24h. The action's
|
|
# cache stores the resolved issue list from a prior pass; if any
|
|
# one pass writes degenerate results (analyzer upgrade, plugin
|
|
# reset, sub-package version drift), every downstream restore
|
|
# replays that list verbatim until the cache key rotates. PR #635
|
|
# hit exactly this — 30+ SA5011/SA4023 false positives against
|
|
# unchanged code while local (cold-cache) runs reported 0 issues.
|
|
# Default is 7 days; 1 day still keeps most runs cache-hot while
|
|
# guaranteeing daily refresh. See BUG-1624.
|
|
cache-invalidation-interval: "1"
|
|
|
|
- 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.
|
|
#
|
|
# Runs in BINARY mode against a freshly-built pad binary rather than
|
|
# source mode (`govulncheck ./...`). Source mode builds an SSA call-
|
|
# graph over the whole dependency tree and can balloon to multiple GB
|
|
# of RAM (BUG-2084); binary mode reads the binary's symbol table — a
|
|
# fraction of the memory, still call-graph-precise, and detects stdlib
|
|
# vulns from the Go version stamped in the binary. The "Create web
|
|
# build placeholder for embed" step above satisfies the //go:embed so
|
|
# the scan build succeeds. Mirrors the Makefile `vuln` target — keep
|
|
# the two in sync.
|
|
#
|
|
# 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 build -o pad-vulnscan ./cmd/pad
|
|
"$(go env GOPATH)/bin/govulncheck" -mode binary pad-vulnscan
|
|
|
|
- name: Run tests
|
|
run: go test ./...
|
|
|
|
- name: Run tests with race detector
|
|
# Runs on both push-to-main AND pull_request. Previously gated to
|
|
# main only because GitHub Actions minutes were billed on private
|
|
# repos; the repo is public now, so PR minutes are free and we'd
|
|
# rather catch race regressions on the contributing branch than
|
|
# after merge. See BUG-1371 (also dropped test-only bcrypt cost
|
|
# via TestMain so this step stays well under the 30m budget).
|
|
#
|
|
# 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. BUG-1913: the suite organically grew past the old 30m
|
|
# budget (734 server-package tests, ~30.3m under -race even on a
|
|
# fast local machine; no single test exceeds 14s — aggregate
|
|
# weight, not a hang), turning most main runs red. 45m restores
|
|
# headroom; genuine deadlocks still hit this and produce the
|
|
# goroutine-dump panic, just up to 15m later. The real fix
|
|
# (cheaper suite: shared fixtures / sharding) is tracked on
|
|
# BUG-1913.
|
|
run: go test -race -timeout=45m ./...
|
|
|
|
- name: Build binary
|
|
run: go build -o pad ./cmd/pad
|
|
|
|
- name: Verify binary runs
|
|
run: ./pad --help
|
|
|
|
native-smoke:
|
|
name: Smoke (${{ matrix.os }})
|
|
runs-on: ${{ matrix.os }}
|
|
timeout-minutes: 10
|
|
defaults:
|
|
run:
|
|
shell: pwsh
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- os: macos-latest
|
|
binary: pad
|
|
path: ./pad
|
|
- os: windows-latest
|
|
binary: pad.exe
|
|
path: .\pad.exe
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
|
|
- uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
|
|
with:
|
|
go-version-file: go.mod
|
|
|
|
- name: Create web build placeholder
|
|
run: |
|
|
New-Item -ItemType Directory -Force web/build | Out-Null
|
|
Set-Content web/build/index.html '<!doctype html>'
|
|
|
|
- name: Build binary
|
|
run: go build -o "${{ matrix.binary }}" ./cmd/pad
|
|
|
|
- name: Verify help output
|
|
run: '& "${{ matrix.path }}" --help'
|
|
|
|
- name: Run CLI smoke test
|
|
run: |
|
|
$ErrorActionPreference = 'Stop'
|
|
$PSNativeCommandUseErrorActionPreference = $true
|
|
$binary = '${{ matrix.path }}'
|
|
$env:PAD_DATA_DIR = Join-Path $env:RUNNER_TEMP 'pad-smoke'
|
|
$env:PAD_BYPASS_SETUP_TOKEN = 'true'
|
|
$stdout = Join-Path $env:RUNNER_TEMP 'pad-server.out.log'
|
|
$stderr = Join-Path $env:RUNNER_TEMP 'pad-server.err.log'
|
|
$server = Start-Process -FilePath $binary -ArgumentList 'server','start','--port','17777' -PassThru -RedirectStandardOutput $stdout -RedirectStandardError $stderr
|
|
|
|
try {
|
|
$ready = $false
|
|
for ($attempt = 0; $attempt -lt 60; $attempt++) {
|
|
try {
|
|
Invoke-WebRequest -UseBasicParsing http://127.0.0.1:17777/api/v1/health | Out-Null
|
|
$ready = $true
|
|
break
|
|
} catch {
|
|
Start-Sleep -Seconds 1
|
|
}
|
|
}
|
|
if (-not $ready) {
|
|
Get-Content $stdout, $stderr -ErrorAction SilentlyContinue
|
|
throw 'Pad server did not become ready'
|
|
}
|
|
|
|
& $binary auth configure --mode local --port 17777
|
|
& $binary auth setup --email smoke@example.com --name Smoke --password 'SmokePass123!'
|
|
& $binary workspace create Smoke --slug smoke --template startup
|
|
|
|
$item = (& $binary --workspace smoke --format json item create task 'Native smoke item') | ConvertFrom-Json
|
|
$shown = (& $binary --workspace smoke --format json item show $item.ref) | ConvertFrom-Json
|
|
if ($shown.title -ne 'Native smoke item') {
|
|
throw "Unexpected item title: $($shown.title)"
|
|
}
|
|
} finally {
|
|
Stop-Process -Id $server.Id -ErrorAction SilentlyContinue
|
|
}
|
|
|
|
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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
|
|
- uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
|
|
with:
|
|
go-version: "1.26"
|
|
|
|
- name: Allow Go to fetch the toolchain go.mod pins
|
|
# See the identical step in the `go` job — setup-go pins
|
|
# GOTOOLCHAIN=local, blocking the 1.26.5 fetch go.mod requires.
|
|
run: echo "GOTOOLCHAIN=auto" >> "$GITHUB_ENV"
|
|
|
|
- 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
|
|
env:
|
|
PAD_TEST_POSTGRES_URL: "postgres://pad:pad@localhost:5432/pad?sslmode=disable"
|
|
# Runs on both push-to-main AND pull_request — see SQLite race-step
|
|
# comment for the public-repo / BUG-1371 reasoning.
|
|
#
|
|
# Headroom over the default 10m. PostgreSQL adds latency on
|
|
# every CREATE/DROP, and the PLAN-866 attachment work pushed the
|
|
# cumulative wall over 20m. The bootstrap-user bcrypt cost that
|
|
# blew past 30m on main (BUG-1371) is now handled by TestMain
|
|
# dropping the cost to bcrypt.MinCost for test binaries.
|
|
# BUG-1913: raised 30m → 45m alongside the SQLite step — the
|
|
# suite's aggregate runtime crossed the old budget (this job
|
|
# variant failed main at f235a04 with the same timeout panic).
|
|
run: go test -race -timeout=45m ./... -count=1
|
|
|
|
web:
|
|
name: Web
|
|
runs-on: ubuntu-latest
|
|
defaults:
|
|
run:
|
|
working-directory: web
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
|
|
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
|
with:
|
|
node-version: "24"
|
|
cache: "npm"
|
|
cache-dependency-path: web/package-lock.json
|
|
|
|
- name: Install dependencies
|
|
run: npm ci
|
|
|
|
- name: Check coordinated Tiptap pins
|
|
# The Y.Doc/ProseMirror schema is shared across @tiptap/core,
|
|
# @tiptap/extension-collaboration, @tiptap/y-tiptap and @tiptap/pm.
|
|
# A stray `npm update` that slides one of them can silently change
|
|
# the persisted Y.Doc shape, producing divergent collab ops the
|
|
# relay can't reconcile (see CLAUDE.md "Tiptap multi-package
|
|
# coordinated bumps" and BUG-2009). This guard fails if any of them
|
|
# loses its exact pin in package.json or resolves to more than one
|
|
# version in the lockfile.
|
|
run: npm run check:tiptap-pins
|
|
|
|
- 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
|
|
|
|
- name: Run web unit tests (vitest)
|
|
run: npm run test
|
|
|
|
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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
|
|
- uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
|
|
with:
|
|
go-version: "1.26"
|
|
|
|
- name: Allow Go to fetch the toolchain go.mod pins
|
|
# See the identical step in the `go` job — setup-go pins
|
|
# GOTOOLCHAIN=local, blocking the 1.26.5 fetch go.mod requires
|
|
# (the "Build pad binary" step below fails without this).
|
|
run: echo "GOTOOLCHAIN=auto" >> "$GITHUB_ENV"
|
|
|
|
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
|
with:
|
|
node-version: "24"
|
|
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
|
|
|
|
# Playwright browser binaries are downloaded from cdn.playwright.dev,
|
|
# which occasionally hangs (PR #635 hit two consecutive 10-minute
|
|
# timeouts during a CDN slow patch — see BUG-1625). Cache them per
|
|
# @playwright/test version so warm-cache runs skip the ~150 MB
|
|
# Chromium download entirely; only the apt system libraries
|
|
# (libatk, libnss, libcups, …) need a fresh install, which is
|
|
# ~10s on a healthy runner. Cache key is the resolved version from
|
|
# package-lock.json so a Playwright bump auto-invalidates.
|
|
- name: Get Playwright version
|
|
id: playwright-version
|
|
working-directory: web
|
|
run: echo "version=$(node -p "require('@playwright/test/package.json').version")" >> $GITHUB_OUTPUT
|
|
|
|
- name: Cache Playwright browsers
|
|
id: playwright-cache
|
|
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
|
with:
|
|
path: ~/.cache/ms-playwright
|
|
key: playwright-${{ runner.os }}-${{ steps.playwright-version.outputs.version }}-chromium
|
|
|
|
- name: Install Playwright browsers (cache miss)
|
|
if: steps.playwright-cache.outputs.cache-hit != 'true'
|
|
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: Install Playwright system deps (cache hit)
|
|
if: steps.playwright-cache.outputs.cache-hit == 'true'
|
|
working-directory: web
|
|
# When the browser binary cache hits, we still need the apt-level
|
|
# system libraries on the fresh runner — `install-deps` does just
|
|
# that without re-downloading the browser binary itself.
|
|
run: npx playwright install-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@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
with:
|
|
name: playwright-report
|
|
path: web/playwright-report/
|
|
retention-days: 14
|