Skip to content

fix(dx): broaden lefthook eslint glob to lint top-level app files (ma… #5

fix(dx): broaden lefthook eslint glob to lint top-level app files (ma…

fix(dx): broaden lefthook eslint glob to lint top-level app files (ma… #5

Workflow file for this run

name: CI
on:
pull_request: {}
push:
branches: [refactor/auth-ui-rebuild, main]
paths-ignore:
- 'docs/**'
- 'README.md'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
env:
BUN_CACHE: ~/.bun/install/cache
CYPRESS_CACHE_FOLDER: ~/.cache/Cypress
jobs:
install:
name: Install Dependencies
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
with: { bun-version: 1.3.14 } # renovate: datasource=docker depName=oven/bun
- uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
id: cache-deps
with:
path: |
${{ env.BUN_CACHE }}
**/node_modules
key: ${{ runner.os }}-deps-${{ hashFiles('**/bun.lock', '**/package.json') }}
- if: steps.cache-deps.outputs.cache-hit != 'true'
run: bun install --frozen-lockfile
lint:
name: Lint
needs: install
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
with: { bun-version: 1.3.14 } # renovate: datasource=docker depName=oven/bun
- uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
with:
path: |
${{ env.BUN_CACHE }}
**/node_modules
key: ${{ runner.os }}-deps-${{ hashFiles('**/bun.lock', '**/package.json') }}
- run: bun run lint:ci
typecheck:
name: Type Check
needs: install
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
with: { bun-version: 1.3.14 } # renovate: datasource=docker depName=oven/bun
- uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
with:
path: |
${{ env.BUN_CACHE }}
**/node_modules
key: ${{ runner.os }}-deps-${{ hashFiles('**/bun.lock', '**/package.json') }}
- run: bun run typecheck
unit-tests:
name: Unit Tests
needs: install
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
with: { bun-version: 1.3.14 } # renovate: datasource=docker depName=oven/bun
- uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
with:
path: |
${{ env.BUN_CACHE }}
**/node_modules
key: ${{ runner.os }}-deps-${{ hashFiles('**/bun.lock', '**/package.json') }}
- run: bun run test:unit
i18n-check:
name: i18n Catalogs Fresh
needs: install
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
with: { bun-version: 1.3.14 } # renovate: datasource=docker depName=oven/bun
- uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
with:
path: |
${{ env.BUN_CACHE }}
**/node_modules
key: ${{ runner.os }}-deps-${{ hashFiles('**/bun.lock', '**/package.json') }}
# Catches commits made with --no-verify that bypass the lefthook i18n hook.
- run: bun run i18n:extract && bun run i18n:compile
env:
CI: '1'
- run: git diff --exit-code -- app/modules/i18n/locales
supply-chain:
name: Supply Chain (audit + SBOM)
needs: install
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
with: { bun-version: 1.3.14 } # renovate: datasource=docker depName=oven/bun
- uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
with:
path: |
${{ env.BUN_CACHE }}
**/node_modules
key: ${{ runner.os }}-deps-${{ hashFiles('**/bun.lock', '**/package.json') }}
- name: Dependency audit (blocking)
# All ignored advisories are dev/build-only — they never ship (the Dockerfile
# installs --production). Runtime advisories (js-yaml, @opentelemetry/core) were
# fixed via dependency bumps, so none are ignored here.
# GHSA-hmw2-7cc7-3qxx form-data <- cypress, start-server-and-test (dev)
# GHSA-gv7w-rqvm-qjhr esbuild <- @lingui/cli, vite (build)
# GHSA-g7r4-m6w7-qqqr esbuild <- @lingui/cli, vite (build)
run: >-
bun audit
--ignore=GHSA-hmw2-7cc7-3qxx
--ignore=GHSA-gv7w-rqvm-qjhr
--ignore=GHSA-g7r4-m6w7-qqqr
- name: Generate SBOM (CycloneDX)
run: bunx @cyclonedx/cdxgen@11.10.0 -t js -o sbom.cdx.json --spec-version 1.5
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: sbom-cyclonedx
path: sbom.cdx.json
retention-days: 90
build:
name: Build
needs: [lint, typecheck]
runs-on: ubuntu-latest
if: ${{ !failure() && !cancelled() }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
with: { bun-version: 1.3.14 } # renovate: datasource=docker depName=oven/bun
- uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
with:
path: |
${{ env.BUN_CACHE }}
**/node_modules
key: ${{ runner.os }}-deps-${{ hashFiles('**/bun.lock', '**/package.json') }}
- run: bun run build
- run: bun run size
- uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
with:
path: build
key: build-${{ github.sha }}
e2e:
name: E2E (fast, fake provider)
needs: install
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
with: { bun-version: 1.3.14 } # renovate: datasource=docker depName=oven/bun
- uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
with:
path: |
${{ env.BUN_CACHE }}
**/node_modules
key: ${{ runner.os }}-deps-${{ hashFiles('**/bun.lock', '**/package.json') }}
- run: bunx cypress install
- run: bun run test:e2e:fast
- if: failure()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: e2e-artifacts-${{ github.run_id }}
path: |
cypress/videos
cypress/screenshots
retention-days: 7
if-no-files-found: warn
status-check:
name: Final Status Check
needs: [install, lint, typecheck, unit-tests, i18n-check, supply-chain, build, e2e]
if: always()
runs-on: ubuntu-latest
steps:
- name: Check Workflow Status
run: |
if [[ "${{ contains(needs.*.result, 'failure') }}" == "true" ]]; then
echo "❌ One or more jobs failed"
exit 1
elif [[ "${{ contains(needs.*.result, 'cancelled') }}" == "true" ]]; then
echo "⚠️ One or more jobs were cancelled"
exit 1
else
echo "✅ All jobs passed"
fi
publish-container-image:
name: Publish Container Image
needs: [status-check]
if: ${{ github.event_name == 'push' && !failure() && !cancelled() }}
permissions:
id-token: write
contents: read
packages: write
attestations: write
uses: datum-cloud/actions/.github/workflows/publish-docker.yaml@545f34cd6f35e9688c9a04a7e890281bcdbaefd2 # v1.14.0
with:
image-name: auth-ui
# NOTE: `secrets: inherit` is required because the upstream workflow
# references `secrets.SENTRY_AUTH_TOKEN` without declaring it under
# `workflow_call.secrets`. Once upstream declares it, switch to an
# explicit `secrets:` block passing only SENTRY_AUTH_TOKEN.
secrets: inherit
publish-kustomize-bundle:
name: Publish Kustomize Bundle
needs: [publish-container-image]
if: ${{ github.event_name == 'push' && !failure() && !cancelled() }}
permissions:
id-token: write
contents: read
packages: write
uses: datum-cloud/actions/.github/workflows/publish-kustomize-bundle.yaml@545f34cd6f35e9688c9a04a7e890281bcdbaefd2 # v1.14.0
with:
bundle-name: ghcr.io/datum-cloud/auth-ui-kustomize
bundle-path: config
image-overlays: config/base
image-name: ghcr.io/datum-cloud/auth-ui
pr-comment:
name: PR Test Summary
needs: [unit-tests, e2e]
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
permissions:
contents: read
pull-requests: write
actions: read
steps:
- name: Build test summary
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
with:
script: |
const runId = context.runId;
const fs = require('fs');
const runUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${runId}`;
const { data: jobs } = await github.rest.actions.listJobsForWorkflowRun({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: runId,
});
const testJobs = jobs.jobs.filter(j =>
j.name === 'Unit Tests' || j.name.startsWith('E2E')
);
const statusEmoji = (c) => {
if (!c || c === 'skipped') return '⏭️';
if (c === 'success') return '✅';
if (c === 'failure') return '❌';
if (c === 'cancelled') return '🚫';
return '❓';
};
let table = '| Job | Status |\n|-----|--------|\n';
for (const job of testJobs.sort((a, b) => a.name.localeCompare(b.name))) {
table += `| ${job.name} | ${statusEmoji(job.conclusion)} ${job.conclusion || 'pending'} |\n`;
}
let body = `## 🧪 Test Summary\n\n${table}\n\n[View workflow run](${runUrl})`;
fs.writeFileSync('pr-summary.md', body);
- uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5
with:
issue-number: ${{ github.event.pull_request.number }}
body-path: pr-summary.md
edit-mode: replace