Skip the backend, frontend, docker-validate, and e2e jobs on the
chore/refresh-screenshots auto-PR opened by the update-screenshots job.
Screenshot PRs only touch docs/images/ and cannot affect build, lint,
or test surfaces, so running the full PR CI suite on them burns ~6
action minutes per release for zero signal. This mirrors the existing
release-please--branches--main--components--sencho skip.
Also short-circuit sync-docs: when a push to main does not touch any
file under docs/, skip the clone, rsync, and commit steps. rsync
--delete would be a no-op anyway, but spinning up the runner and
cloning sencho-docs still burns ~30s per non-docs merge, which adds
up across multiple merges per day. Requires fetch-depth: 2 so the
detect step can diff HEAD~1 HEAD.
Finally, correct the scan-build comment in docker-publish.yml: the
push-build's amd64 leg reuses layers from the buildkit daemon's
in-memory cache (same job, same daemon), not from the shared registry
buildcache. The cache-from pull is a cold-start fallback for the
first-ever run.
* ci: hard-fail PR and release scans on unacknowledged HIGH/CRITICAL CVEs
Make Trivy a real gate instead of an advisory signal:
- PR CI (docker-validate) no longer uses `continue-on-error: true` on the
Trivy step, so any HIGH/CRITICAL finding not in `.trivyignore` fails the PR.
- The release pipeline (docker-publish.yml) now builds an amd64-only scan
image into the local daemon before the multi-arch push-build, re-runs
Trivy against that exact artifact, and only proceeds to the push if the
scan passes. This closes the gap where a CVE landed between PR merge and
release-time rebuild.
- New `.trivyignore` at repo root is the single source of truth for
acknowledged CVEs across both workflows; it starts empty so the first CI
run surfaces the full list, which we then populate with justifications.
* ci: populate .trivyignore with initial HIGH/CRITICAL acknowledgements
First CI run on the hard-fail Trivy policy surfaced 7 unacknowledged
findings. Each has been reviewed and justified inline:
- 6 CVEs in the statically-linked Go modules inside docker-compose v5.1.1
(github.com/docker/docker, buildkit, otel/sdk x2, grpc). These are
transitively bundled and cannot be bumped without an upstream Compose
rebuild. The grpc CVE is already explicitly acknowledged in the
Dockerfile rationale block at Dockerfile:108-111.
- 1 CVE in picomatch 4.0.3 bundled inside the npm CLI that ships with
node:22-alpine. npm is only invoked at build time against our own
package.json, so the ReDoS vector is not reachable.
Every entry has a revisit trigger (next Compose release or next Alpine
node bump).
Pin the push_to_registry job to a GitHub `production` environment so the
DOCKERHUB_USERNAME and DOCKERHUB_TOKEN credentials can live there
instead of as repo-wide secrets. Any future workflow that tries to push
to Docker Hub without declaring this environment will fail to resolve
the credentials, which is exactly the blast-radius reduction we want.
As a side benefit, adding a required reviewer to the `production`
environment in repo settings now turns every release into a manual
approval gate with zero workflow changes. The secrets were already
moved into the environment ahead of this commit, so the next release
run will pick them up seamlessly.
Every published Sencho Docker image is now signed with Sigstore cosign
using GitHub Actions keyless OIDC, and ships with an embedded SBOM plus
SLSA provenance attestation attached as OCI referrers on the image.
Users can verify the signature and inspect the attestations themselves
before pulling an image into production.
cosign verify saelix/sencho:<tag> \
--certificate-identity-regexp "https://github.com/AnsoCode/Sencho/.*" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
The release pipeline now also publishes a new moving minor tag
(saelix/sencho:X.Y, e.g. 0.42) alongside the existing latest and
immutable X.Y.Z tags, so operators who want the latest patch on a given
minor line can pin without chasing every release. Since every 0.x minor
is potentially breaking, the {{major}}-only tag is deferred until 1.0.
cosign is installed via the sigstore/cosign-installer action pinned to
a full commit SHA. The signing step batches every tag produced by
metadata-action into a single cosign invocation pinned to the built
digest, so all tags resolve to the same manifest and we save N-1
Rekor/Fulcio round trips. The job declares id-token: write so the
ambient OIDC token can be minted.
A new docs page (docs/reference/verifying-images.mdx) walks users
through installing cosign, verifying an image, and inspecting the SBOM
and provenance with docker buildx imagetools. A note calls out that
signatures start shipping with v0.43.0, so older images failing
verification is expected behavior and not tampering.
Pin three third-party actions to full commit SHAs with version comments
so dependabot can update them in place without exposing the pipeline to
upstream tag tampering:
- aquasecurity/trivy-action@v0.35.0
- peter-evans/create-pull-request@v8.1.1
- googleapis/release-please-action@v4.4.0
Add a workflow-level permissions: contents: read default to ci.yml, with
update-screenshots keeping its explicit contents: write + pull-requests:
write override. Add the same default to docker-publish.yml (single job).
Expand .dockerignore to explicitly exclude .env*, *.key, *.pem, .github/,
docs/, website/, e2e/, tests/, test-results/, and playwright-report/ as
defense in depth against accidental build-context leaks. None of these
paths are read by any COPY step in Dockerfile.
* ci: optimize workflows to cut redundant runs and add timeout protection
Skip validation jobs (build, test, lint, Docker, E2E) on push-to-main
since code was already validated on the PR. Skip CI entirely for
release-please PRs (version bump only). Add timeout-minutes to all jobs
to prevent hung runners from burning 360 min (GitHub default). Add npm
caching to the start-app composite action. Add concurrency control to
docker-publish. Group Dependabot updates to batch PRs per ecosystem.
Estimated savings: ~10 min per release cycle, ~30-40 min/day.
* chore: add tsbuildinfo to gitignore
* chore: add comprehensive .gitignore
* ci: update CI workflow for GitHub Flow
- Change triggers from develop to main (PRs to main + pushes to main)
- Add concurrency controls to cancel stale runs
- Update docker/build-push-action to v6
- Add descriptive job names for branch protection status checks
- Update screenshot refresh and docs sync to trigger on main pushes
* ci: update docker-publish for GitHub Flow
- Remove develop branch trigger (no more dev tag)
- Keep v* tag trigger for releases
- Update docker/build-push-action to v6
* docs: add community and governance files
- CONTRIBUTING.md with dev setup and PR guidelines
- SECURITY.md with vulnerability reporting policy
- CODE_OF_CONDUCT.md (Contributor Covenant v2.1 reference)
- PR template with conventional commits checklist
- Issue templates for bug reports and feature requests
- CODEOWNERS defaulting to @AnsoCode
- Dependabot config for npm (root, backend, frontend) and GitHub Actions
* docs: add README with badges, quick start, and contributing section
* chore: add LICENSE placeholder and open license decision issue (#100)
* docs: update CLAUDE.md for GitHub Flow branching model
- Replace develop-based Git Flow with GitHub Flow (main only)
- All branches now created off main, PRs target main
- Simplify release checklist (no develop-to-main merge step)
- Update testing strategy to reference Vitest and Playwright
- Fix docs.json reference (was mint.json)
* chore: track CLAUDE.md in version control
Remove CLAUDE.md from .gitignore so project workflow instructions
are versioned alongside the code they govern.
* docs: add MANUAL_STEPS.md for GitHub settings that require UI configuration
- Add docker/setup-qemu-action@v3 to docker-publish.yml (was missing,
causing multi-platform builds to hang indefinitely)
- Add platforms: linux/amd64,linux/arm64 to build-push-action step
- Optimize Dockerfile with --platform=$BUILDPLATFORM on builder stages
so TypeScript compilation runs at native amd64 speed; only the lean
npm ci --omit=dev step runs under QEMU in the final stage, compiling
the three native modules (bcrypt, better-sqlite3, node-pty) for the
correct target architecture — reduces arm64 build time from 6+ hours
to ~15-30 minutes