name: ci on: push: branches: [main] pull_request: branches: [main] jobs: verify: runs-on: easyai-gateway-ci-unprivileged-v2 env: TRIVY_DB_REPOSITORY: ghcr.m.daocloud.io/aquasecurity/trivy-db:2 steps: - name: Checkout without external Actions env: CI_REPOSITORY: ${{ github.repository }} CI_SERVER_URL: ${{ github.server_url }} CI_SHA: ${{ github.sha }} CI_JOB_TOKEN: ${{ github.token }} CI_EVENT_BEFORE: ${{ github.event.before }} CI_PR_BASE_SHA: ${{ github.event.pull_request.base.sha }} run: | set -eu test -n "$CI_JOB_TOKEN" authorization=$(printf 'x-access-token:%s' "$CI_JOB_TOKEN" | base64 | tr -d '\n') git init . git -c "http.extraHeader=AUTHORIZATION: basic $authorization" \ fetch --no-tags "$CI_SERVER_URL/$CI_REPOSITORY.git" "$CI_SHA" for comparison_sha in "$CI_EVENT_BEFORE" "$CI_PR_BASE_SHA"; do case "$comparison_sha" in [0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]*) if test "${#comparison_sha}" -eq 40 && \ test "$comparison_sha" != 0000000000000000000000000000000000000000; then git -c "http.extraHeader=AUTHORIZATION: basic $authorization" \ fetch --no-tags "$CI_SERVER_URL/$CI_REPOSITORY.git" "$comparison_sha" fi ;; esac done unset authorization CI_JOB_TOKEN test ! -f .git/shallow git checkout --detach "$CI_SHA" test "$(git rev-parse HEAD)" = "$CI_SHA" - name: Verify pinned host toolchains run: | go version node --version pnpm --version docker-compose version shellcheck --version trivy --version govulncheck -version - name: Verify production migration safety env: CI_EVENT_NAME: ${{ github.event_name }} CI_EVENT_BEFORE: ${{ github.event.before }} CI_PR_BASE_SHA: ${{ github.event.pull_request.base.sha }} run: | production_base=$(cat deploy/ci/production-migration-base) immutable_base=$CI_EVENT_BEFORE if test "$CI_EVENT_NAME" = pull_request; then immutable_base=$CI_PR_BASE_SHA fi case "$immutable_base" in [0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]*) test "${#immutable_base}" -eq 40 test "$immutable_base" != 0000000000000000000000000000000000000000 ;; *) exit 1 ;; esac git merge-base --is-ancestor "$immutable_base" HEAD node ./scripts/ci-validate-migrations.mjs \ "$production_base" "$immutable_base" - name: Verify Go formatting run: | unformatted=$(gofmt -l apps/api) test -z "$unformatted" || { printf 'Go files require gofmt:\n%s\n' "$unformatted" >&2 exit 1 } - name: Verify Go code working-directory: apps/api env: GOFLAGS: "-p=1" GOMAXPROCS: "1" run: | go vet ./... go test ./... govulncheck ./... - run: pnpm install --frozen-lockfile - run: pnpm lint - run: pnpm test - run: pnpm build - name: Audit JavaScript dependencies run: pnpm audit --audit-level high - name: Validate deployment configuration run: | docker-compose -f docker-compose.yml config --quiet shellcheck scripts/ci-build-images.sh scripts/ci-validate-semver.sh \ scripts/provision-ci-runner.sh tests/ci/ci-build-images-test.sh \ tests/ci/migrations-test.sh tests/ci/pipeline-test.sh \ tests/ci/semver-test.sh ./tests/ci/ci-build-images-test.sh ./tests/ci/migrations-test.sh ./tests/ci/pipeline-test.sh ./tests/ci/semver-test.sh - name: Scan repository run: | trivy fs --scanners vuln,secret,misconfig --severity HIGH,CRITICAL \ --ignore-unfixed --exit-code 1 --timeout 15m --skip-dirs .git \ --skip-dirs node_modules .