chore: #27 CI workflow on the self-hosted runner #3
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/CD | |
| on: | |
| pull_request: | |
| branches: [main] | |
| push: | |
| branches: [main] | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| quality: | |
| name: Format, lint, typecheck, test, build | |
| runs-on: [self-hosted, linux, x64] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Install pnpm | |
| uses: pnpm/action-setup@v4 | |
| with: | |
| version: 10.33.0 | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 24 | |
| cache: pnpm | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Check formatting | |
| run: pnpm format:check | |
| - name: Lint | |
| run: pnpm lint | |
| - name: Typecheck | |
| run: pnpm typecheck | |
| - name: Test | |
| run: pnpm test | |
| - name: Build | |
| run: pnpm build | |
| # Bundle budget, one of our bærekraft measures. The budget is deliberately | |
| # loose today and tightens as the app grows; the point is that CI fails | |
| # before a dependency quietly doubles our payload. | |
| - name: Enforce client bundle budget | |
| run: | | |
| set -euo pipefail | |
| MAX_BYTES=512000 | |
| shopt -s nullglob | |
| found=0 | |
| for f in client/dist/assets/*.js; do | |
| found=1 | |
| size=$(stat -c%s "$f") | |
| echo "$f = ${size} bytes (budget ${MAX_BYTES})" | |
| if [ "$size" -gt "$MAX_BYTES" ]; then | |
| echo "::error::Bundle budget exceeded: $f is ${size} bytes (max ${MAX_BYTES})." | |
| exit 1 | |
| fi | |
| done | |
| if [ "$found" -eq 0 ]; then | |
| echo "::error::No client JS bundle found in client/dist/assets/." | |
| exit 1 | |
| fi | |
| deploy: | |
| name: Deploy to the group VM | |
| needs: quality | |
| if: github.ref == 'refs/heads/main' && github.event_name == 'push' | |
| runs-on: [self-hosted, linux, x64] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Install pnpm | |
| uses: pnpm/action-setup@v4 | |
| with: | |
| version: 10.33.0 | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 24 | |
| cache: pnpm | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Build client | |
| run: pnpm build | |
| - name: Publish to Apache | |
| run: | | |
| set -euo pipefail | |
| find /var/www/html/project2 -mindepth 1 -delete | |
| cp -r client/dist/. /var/www/html/project2/ | |
| chmod -R a+rX /var/www/html/project2 | |
| curl -fsS -o /dev/null -w 'GET /project2/ : %{http_code}\n' http://localhost/project2/ | |
| # crate-api only exists from M2 onward. Fail the deploy loudly if the | |
| # unit is present but down; skip quietly if it has not been created yet. | |
| - name: Restart the GraphQL API if present | |
| run: | | |
| set -euo pipefail | |
| if systemctl list-unit-files | grep -q '^crate-api.service'; then | |
| sudo systemctl restart crate-api | |
| sleep 2 | |
| curl -fsS -o /dev/null -w 'POST /graphql : %{http_code}\n' \ | |
| -X POST http://localhost/graphql \ | |
| -H 'content-type: application/json' \ | |
| -d '{"query":"{ __typename }"}' | |
| else | |
| echo "crate-api.service not installed yet (arrives in M2). Skipping." | |
| fi |