mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-10 10:49:35 +00:00
efcc06d50b
* ci: harden CI and supply-chain pipeline * Add frontend Vitest step to ci.yml so the 241 existing frontend tests run on every PR (mirrors the backend build/test/lint/audit order). * Pin Node 26 as a single source of truth: new .node-version, node-version-file on all setup-node calls, engines.node ">=26.0.0" in all three package.json files. Matches the Dockerfile's node:26-alpine. * SHA-pin remaining mutable actions in the start-app composite (actions/setup-node v6, actions/cache v4.3.0). * Pin Dockerfile supply-chain inputs: golang:1.26.3-alpine by sha256 digest in both builder stages; replace mutable-tag git clone with commit-SHA fetch for docker/cli (v29.4.1) and docker/compose (v5.1.3). LDFLAGS version strings and otel patch preserved unchanged. * Ref-scope docker-publish concurrency so two different release tags cannot cancel each other; same-ref reruns still cancel as before. * Harden CLA workflow: drop actions:write from permissions; tighten the issue_comment trigger to PRs only (github.event.issue.pull_request != null) matching the two documented CLA phrases. No PR code is checked out. * Drop trivy-version: latest from both Trivy scans so the SHA-pinned aquasecurity/trivy-action governs the bundled binary version. The HIGH/CRITICAL gate, severity filter, and trivy.yaml (OpenVEX) are unchanged. * Restructure Dependabot: add applies-to: security-updates groups for npm (root/backend/frontend), docker, and github-actions; switch github-actions to directories so the local composite action is monitored alongside the top-level workflows. * Add a daily scheduled SARIF security scan (security-scan.yml): two parallel jobs scanning saelix/sencho:latest and a fresh main HEAD build, uploading to GitHub code scanning. Least-privilege (contents: read, security-events: write). Visibility only; existing PR-blocking and release-blocking Trivy gates are not weakened. Validation: backend tsc clean; frontend tsc clean; frontend npm test 27 files / 241 tests pass; npm audit --audit-level=high passes at root, backend, and frontend; docker buildx build --check passes with no warnings (all pinned digests resolve from the registry). * ci(frontend): set explicit jsdom URL so localStorage initializes in CI jsdom does not instantiate window.localStorage / sessionStorage when the document has the opaque about:blank origin. Five frontend test files that call localStorage.clear() in beforeEach started failing once the new frontend Vitest step in this PR began running them on Linux CI runners. Configuring environmentOptions.jsdom.url with a real same-origin URL is the documented Vitest 4.x workaround and is a config-only change. All 27 test files (241 tests) pass locally with the fix applied.
120 lines
4.2 KiB
YAML
120 lines
4.2 KiB
YAML
name: Start Sencho App
|
|
description: >
|
|
Shared setup for integration jobs: installs deps, builds backend,
|
|
starts backend + frontend dev servers, waits for readiness,
|
|
and installs Playwright browsers.
|
|
|
|
inputs:
|
|
jwt-secret:
|
|
required: false
|
|
default: 'ci-test-secret-key-not-for-production'
|
|
compose-dir:
|
|
required: false
|
|
default: '/tmp/compose'
|
|
port:
|
|
required: false
|
|
default: '1852'
|
|
skip-backend-build:
|
|
description: >
|
|
When 'true', skip running `npm run build` in backend/ and assume the
|
|
caller has already materialized backend/dist (e.g. via download-artifact
|
|
from an upstream job that already built and verified it). Leave 'false'
|
|
for standalone invocations that do not run in a job graph with a
|
|
prior build step.
|
|
required: false
|
|
default: 'false'
|
|
|
|
runs:
|
|
using: composite
|
|
steps:
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
|
|
with:
|
|
node-version-file: '.node-version'
|
|
cache: 'npm'
|
|
cache-dependency-path: |
|
|
package-lock.json
|
|
backend/package-lock.json
|
|
frontend/package-lock.json
|
|
|
|
- name: Install root dependencies (Playwright)
|
|
shell: bash
|
|
run: npm ci
|
|
|
|
- name: Install backend dependencies
|
|
shell: bash
|
|
run: npm ci
|
|
working-directory: ./backend
|
|
|
|
- name: Build backend
|
|
if: inputs.skip-backend-build != 'true'
|
|
shell: bash
|
|
run: npm run build
|
|
working-directory: ./backend
|
|
|
|
- name: Install frontend dependencies
|
|
shell: bash
|
|
run: npm ci
|
|
working-directory: ./frontend
|
|
|
|
- name: Create compose directory and log dir
|
|
shell: bash
|
|
run: |
|
|
mkdir -p ${{ inputs.compose-dir }}
|
|
mkdir -p "${{ github.workspace }}/ci-logs"
|
|
|
|
# Log files live under $GITHUB_WORKSPACE so actions/upload-artifact@v4+ can
|
|
# include them alongside repo-relative paths like e2e/report/. Mixing those
|
|
# with /tmp paths makes '/' the common root and v4+ strips the absolute
|
|
# entries from the artifact. `stdbuf -oL -eL` forces line-buffered output
|
|
# so a crash doesn't lose the final few hundred lines to block buffering.
|
|
- name: Start backend
|
|
shell: bash
|
|
run: stdbuf -oL -eL node dist/index.js > "${{ github.workspace }}/ci-logs/backend.log" 2>&1 &
|
|
working-directory: ./backend
|
|
env:
|
|
JWT_SECRET: ${{ inputs.jwt-secret }}
|
|
COMPOSE_DIR: ${{ inputs.compose-dir }}
|
|
PORT: ${{ inputs.port }}
|
|
NODE_ENV: test
|
|
|
|
- name: Start frontend dev server
|
|
shell: bash
|
|
run: stdbuf -oL -eL npm run dev > "${{ github.workspace }}/ci-logs/frontend.log" 2>&1 &
|
|
working-directory: ./frontend
|
|
|
|
- name: Wait for services to be ready
|
|
shell: bash
|
|
run: npx wait-on http://localhost:${{ inputs.port }}/api/health http://localhost:5173 --timeout 30000
|
|
|
|
# Playwright bundles Chrome for Testing (~170MB) and FFmpeg. Downloading
|
|
# them on every E2E run is the single largest cost in this composite:
|
|
# observed ~4m15s cold vs ~10s warm when the path is cached. Cache the
|
|
# download under a key pinned to the @playwright/test version so a
|
|
# future bump invalidates automatically.
|
|
- name: Read Playwright version
|
|
id: playwright-version
|
|
shell: bash
|
|
run: |
|
|
version=$(node -p "require('./package.json').devDependencies['@playwright/test'].replace(/^[\^~]/, '')")
|
|
echo "version=$version" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Cache Playwright browsers
|
|
id: playwright-cache
|
|
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
|
with:
|
|
path: ~/.cache/ms-playwright
|
|
key: playwright-${{ runner.os }}-${{ steps.playwright-version.outputs.version }}
|
|
|
|
# OS deps are apt packages under /var, which actions/cache does not
|
|
# preserve, so they have to be reinstalled every run regardless of the
|
|
# browser cache state. It is fast (~10s).
|
|
- name: Install Playwright OS dependencies
|
|
shell: bash
|
|
run: npx playwright install-deps chromium
|
|
|
|
- name: Install Playwright browsers
|
|
if: steps.playwright-cache.outputs.cache-hit != 'true'
|
|
shell: bash
|
|
run: npx playwright install chromium
|