Repository navigation
chore: release #534
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: | |
| workflow_dispatch: | |
| push: | |
| branches: | |
| - main | |
| pull_request: | |
| branches: | |
| - main | |
| concurrency: | |
| group: '${{ github.workflow }}-${{ github.head_ref }}' | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| permissions: {} | |
| defaults: | |
| run: | |
| shell: bash | |
| jobs: | |
| build-and-test: | |
| name: Build and test ${{ matrix.node }} on ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| node: [24, 26] | |
| os: [ubuntu-24.04, macos-15] | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 10 | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| - name: Install Dependencies | |
| uses: marcalexiei/github-actions/setup-node-and-pnpm@92c64c084d3479cff756151cb8163d03608f2acd # v2.4.2 | |
| with: | |
| node-version: ${{ matrix.node }} | |
| - name: Build packages | |
| run: pnpm run build:packages | |
| - name: Run tests | |
| run: pnpm run test | |
| code-checks: | |
| name: Code checks | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 5 | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| - name: Install Dependencies | |
| uses: marcalexiei/github-actions/setup-node-and-pnpm@92c64c084d3479cff756151cb8163d03608f2acd # v2.4.2 | |
| - name: Format | |
| run: pnpm run format:check | |
| # `astro:content` is a virtual module, so the type-aware rules see an error type | |
| # in `content.config.ts` until astro has written `.astro/types.d.ts`. | |
| - name: Sync the docs site's generated types | |
| run: pnpm run docs:sync | |
| - name: Lint | |
| run: pnpm run lint:ci | |
| - name: Lint (knip) | |
| run: pnpm run lint:knip | |
| - name: Lint (generated GraphQL types) | |
| run: pnpm --filter ./packages/core/ run check-graphql-types | |
| - name: Typecheck | |
| run: pnpm run typecheck | |
| # Relative specifiers are written `.ts` and rewritten on emit, so the published | |
| # resolution is checked rather than assumed. `typecheck` above leaves the build in | |
| # place for it. | |
| - name: Lint (packaging and published types) | |
| run: pnpm run lint:publish | |
| docs: | |
| name: Docs site | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 10 | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| - name: Install Dependencies | |
| uses: marcalexiei/github-actions/setup-node-and-pnpm@92c64c084d3479cff756151cb8163d03608f2acd # v2.4.2 | |
| with: | |
| save-cache: false | |
| - name: Lint (generated theme page) | |
| run: pnpm --filter ./apps/docs run check-themes-page | |
| # The anvil's recorded samples are the only thing standing between a changed query and a | |
| # page that cannot draw. Needs no token, so unlike the recorder it runs here. | |
| - name: Lint (anvil samples) | |
| run: pnpm --filter ./apps/docs run check-anvil-samples | |
| - name: Typecheck | |
| run: pnpm --filter ./apps/docs run typecheck | |
| # The build is what checks the site: a page referencing a preview nobody rendered, a | |
| # dead internal link, or a fetcher reference core no longer backs, each fail it. | |
| # That last one also notices a TypeScript release moving the unstable API it reads. | |
| - name: Build | |
| run: pnpm run docs:build | |
| # The anvil is the only page here that ships JavaScript, and nothing else checks it in a | |
| # browser. It serves the build from the step above. | |
| - name: Install Playwright browser | |
| run: pnpm --filter ./apps/docs exec playwright install --with-deps chromium | |
| - name: Test (anvil, end to end) | |
| run: pnpm --filter ./apps/docs run test:e2e | |
| image: | |
| name: Server image | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 10 | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| - name: Set up Buildx | |
| uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1 | |
| # amd64 only and no push: this is here so a broken Dockerfile fails on the pull request | |
| # rather than during a release. `publish-image.yml` is what builds both architectures. | |
| - name: Build the image | |
| uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7.4.0 | |
| with: | |
| context: . | |
| file: apps/server/Dockerfile | |
| load: true | |
| tags: github-stats-forge-server:ci | |
| # No build step, so only starting the image proves the sources resolve inside it. | |
| - name: Run it | |
| run: | | |
| docker run -d --name cards -p 9000:9000 github-stats-forge-server:ci | |
| for _ in $(seq 1 30); do | |
| if curl -sf http://127.0.0.1:9000/healthz > /dev/null; then break; fi | |
| sleep 1 | |
| done | |
| curl -sf http://127.0.0.1:9000/healthz | |
| # no token, so this draws the `no_tokens` card — route, renderer and headers all the same | |
| curl -s -D- -o /dev/null 'http://127.0.0.1:9000/api/stats?username=x' | tee /dev/stderr | grep -q 'card-error-code: no_tokens' | |
| docker rm -f cards | |
| ci-ok: | |
| name: CI OK | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 1 | |
| if: ${{ always() }} | |
| needs: | |
| - build-and-test | |
| - code-checks | |
| - docs | |
| - image | |
| steps: | |
| - name: Exit with error if some jobs are not successful | |
| run: exit 1 | |
| if: ${{ always() && (contains(needs.*.result, 'failure') || contains(needs.*.result, 'skipped') || contains(needs.*.result, 'cancelled')) }} |