name: ci on: push: branches: [main] tags: ['v*'] pull_request: jobs: verify: runs-on: easyai-gateway-linux env: IMAGE_TAG: ${{ github.sha }} 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 }} 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 --depth=1 "$CI_SERVER_URL/$CI_REPOSITORY.git" "$CI_SHA" unset authorization CI_JOB_TOKEN git checkout --detach FETCH_HEAD - name: Verify pinned host toolchains run: | go version node --version pnpm --version docker version docker compose version docker buildx version shellcheck --version trivy --version govulncheck -version - name: Verify Production deployment prerequisites if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') run: | grep -Eq '^NoNewPrivs:[[:space:]]+0$' /proc/self/status test -x /usr/local/sbin/easyai-ai-gateway-release sudo -n -l /usr/local/sbin/easyai-ai-gateway-release "$IMAGE_TAG" >/dev/null - name: Verify release tag ancestry if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') env: CI_REPOSITORY: ${{ github.repository }} CI_SERVER_URL: ${{ github.server_url }} CI_SHA: ${{ github.sha }} CI_JOB_TOKEN: ${{ github.token }} run: | set -eu tag_name=${GITHUB_REF#refs/tags/} printf '%s' "$tag_name" | grep -Eq '^v[0-9]+\.[0-9]+\.[0-9]+([-.][0-9A-Za-z.-]+)?$' authorization=$(printf 'x-access-token:%s' "$CI_JOB_TOKEN" | base64 | tr -d '\n') git -c "http.extraHeader=AUTHORIZATION: basic $authorization" \ fetch --no-tags --depth=200 "$CI_SERVER_URL/$CI_REPOSITORY.git" \ main:refs/remotes/origin/main unset authorization CI_JOB_TOKEN test "$(git rev-parse HEAD)" = "$CI_SHA" git merge-base --is-ancestor "$CI_SHA" refs/remotes/origin/main - 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 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/provision-ci-runner.sh tests/ci/pipeline-test.sh ./tests/ci/pipeline-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 . - run: ./scripts/ci-build-images.sh - name: Deploy verified release to Production if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') env: CI_SHA: ${{ github.sha }} run: | test "$(git rev-parse HEAD)" = "$CI_SHA" sudo -n /usr/local/sbin/easyai-ai-gateway-release "$CI_SHA"