Merge pull request #226 from DrexelTriangle/chore/trim-slack-unavaila… #264
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| pull_request: | |
| branches: | |
| - main | |
| push: | |
| branches: | |
| - main | |
| workflow_dispatch: | |
| concurrency: | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| jobs: | |
| backend: | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: server | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-go@v5 | |
| with: | |
| go-version-file: server/go.mod | |
| cache-dependency-path: server/go.sum | |
| - name: Test | |
| run: go test ./... | |
| - name: Race test | |
| run: go test -race ./... | |
| - name: Vet | |
| run: go vet ./... | |
| frontend: | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: frontend | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| cache: npm | |
| cache-dependency-path: frontend/package-lock.json | |
| - name: Clean install | |
| run: npm ci | |
| - name: Lint | |
| run: npm run lint | |
| - name: Test | |
| run: npm test | |
| - name: Build | |
| run: npm run build | |
| # The Docker build regenerates the Swagger docs from the handler annotations, | |
| # so the binary always serves a current spec -- but server/docs is also | |
| # committed, and the Pages site publishes that committed copy. Nothing forced | |
| # the two to agree, so annotations could change without a follow-up | |
| # `swag init` and the published reference would drift from the real API with | |
| # no signal. Regenerate here and fail on any diff. | |
| swagger-docs: | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: server | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-go@v5 | |
| with: | |
| go-version-file: server/go.mod | |
| cache-dependency-path: server/go.sum | |
| # Pinned to the same version server/Dockerfile installs. A different | |
| # version would report drift the real build never produces. | |
| - name: Install swag | |
| run: go install github.com/swaggo/swag/cmd/swag@v1.16.6 | |
| - name: Regenerate docs | |
| run: swag init --parseDependency --parseInternal | |
| - name: Committed docs are current | |
| run: | | |
| if ! git diff --exit-code -- docs; then | |
| echo "::error file=server/docs/swagger.json::server/docs is stale. Run 'swag init --parseDependency --parseInternal' in server/ and commit the result." | |
| exit 1 | |
| fi | |
| docker-builds: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: docker/setup-buildx-action@v3 | |
| - name: Build backend image | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: ./server | |
| file: ./server/Dockerfile | |
| push: false | |
| tags: triangle-cms-backend:${{ github.sha }} | |
| cache-from: type=gha,scope=backend | |
| cache-to: type=gha,mode=max,scope=backend | |
| - name: Build frontend image | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: ./frontend | |
| file: ./frontend/Dockerfile | |
| push: false | |
| tags: triangle-cms-frontend:${{ github.sha }} | |
| cache-from: type=gha,scope=frontend | |
| cache-to: type=gha,mode=max,scope=frontend | |
| # The deployment scripts are the least reversible code in the repo, so their | |
| # test suite runs on every PR. It stubs docker/curl/nginx on PATH and needs no | |
| # daemon, database, or privileges. | |
| deploy-scripts: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Deploy script tests | |
| run: deploy/scripts/deploy_scripts_test.sh | |
| # The Python in scripts/ was previously untested. A full reseed cannot run | |
| # here -- it needs the WordPress export zip, which is not in the repo, and a | |
| # local Docker stack -- so this covers the parts that can fail silently: the | |
| # scripts compiling at all, the seed generator's id=0 guarantee, and the | |
| # reseed script's refusal to destroy data unattended. | |
| scripts: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.12' | |
| - name: Compile | |
| run: python -m compileall -q scripts/ | |
| - name: Reseed script help | |
| run: python ./scripts/reseed_from_etl.py --help | |
| # The non-TTY guard is the only thing standing between an automated | |
| # context and a destroyed database, so assert it stays a guard: this must | |
| # FAIL to proceed. Without a Docker daemon the run would abort in | |
| # preflight anyway, so accept either refusal -- what is not acceptable is | |
| # a clean exit, which would mean it sailed past the confirmation. | |
| - name: Refuses to destroy data unattended | |
| run: | | |
| if python ./scripts/reseed_from_etl.py --skip-etl < /dev/null; then | |
| echo "::error file=scripts/reseed_from_etl.py::reseed script exited 0 without a TTY and without --yes" | |
| exit 1 | |
| fi | |
| # articles has a real row with id = 0, which survives a load only under | |
| # NO_AUTO_VALUE_ON_ZERO. Nothing else in CI covers this, and a renumbered | |
| # id=0 orphans every articles_authors and seo row that references it. | |
| - name: Seed generator preserves the id=0 row | |
| run: | | |
| set -euo pipefail | |
| etl=$(mktemp -d); out=$(mktemp -d) | |
| printf "INSERT INTO authors (\`login\`) VALUES ('x');\n" > "$etl/authors.sql" | |
| printf "INSERT INTO articles (\`author_ids\`, \`comment_status\`) VALUES ('x','open');\n" > "$etl/articles.sql" | |
| printf "INSERT INTO articles_authors (\`author_id\`) VALUES (1);\n" > "$etl/articles_authors.sql" | |
| printf "INSERT INTO seo (\`yoast_tag_data\`) VALUES ('{}');\n" > "$etl/seo.sql" | |
| python ./scripts/generate_wordpress_sql.py "$etl" "$out" | |
| if ! head -1 "$out/02-articles.sql" | grep -q 'NO_AUTO_VALUE_ON_ZERO'; then | |
| echo "::error file=scripts/generate_wordpress_sql.py::02-articles.sql lacks the NO_AUTO_VALUE_ON_ZERO preamble; the id=0 article would be renumbered on load" | |
| exit 1 | |
| fi | |
| # A mention of the mode in a comment must not be mistaken for setting | |
| # it -- that regression would silently skip the preamble. | |
| printf -- "-- NO_AUTO_VALUE_ON_ZERO handled upstream\nINSERT INTO articles (\`author_ids\`, \`comment_status\`) VALUES ('y','open');\n" > "$etl/articles.sql" | |
| python ./scripts/generate_wordpress_sql.py "$etl" "$out" | |
| if ! head -1 "$out/02-articles.sql" | grep -q '^SET sql_mode'; then | |
| echo "::error file=scripts/generate_wordpress_sql.py::a commented mention of NO_AUTO_VALUE_ON_ZERO suppressed the preamble" | |
| exit 1 | |
| fi | |
| compose-validation: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Validate Delta Compose config | |
| env: | |
| CMS_IMAGE_TAG: ${{ github.sha }} | |
| DB_NAME: triangle | |
| DB_USER: triangle_user | |
| DB_PASSWORD: ci-placeholder | |
| DB_HOST: db-host-placeholder | |
| DB_PORT: "3306" | |
| OIDC_ISSUER_URL: http://oidc-placeholder.invalid | |
| OIDC_CLIENT_ID: ci-placeholder | |
| OIDC_CLIENT_SECRET: ci-placeholder | |
| FRONTEND_ORIGIN: http://delta-placeholder | |
| OIDC_REDIRECT_URI: http://delta-placeholder/auth/callback | |
| # CMS_EMBEDDINGS_TAG is derived rather than hardcoded, so this also | |
| # checks that the derivation deploy.sh uses still resolves. | |
| run: | | |
| CMS_EMBEDDINGS_TAG="$(git rev-parse HEAD:embeddings)" \ | |
| docker compose -f deploy/compose.cms.yml config >/dev/null |