chore(deps): Bump the npm-dependencies group in /site with 2 updates #310
Workflow file for this run
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: | |
| types: [opened, synchronize, reopened, edited] | |
| push: | |
| branches: | |
| - main | |
| defaults: | |
| run: | |
| shell: bash -xeuo pipefail {0} | |
| concurrency: | |
| group: "ci-${{ github.ref }}" | |
| cancel-in-progress: true | |
| permissions: {} | |
| jobs: | |
| generate-matrix: | |
| name: Generate matrix | |
| runs-on: ubuntu-slim | |
| permissions: | |
| contents: read | |
| outputs: | |
| matrix: ${{ steps.matrix.outputs.matrix }} | |
| steps: | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| - name: Generate CI matrix | |
| id: matrix | |
| env: | |
| BASE_SHA: ${{ github.event.pull_request.base.sha }} | |
| EVENT_NAME: ${{ github.event_name }} | |
| run: | | |
| # Push to main: run test-tsan so Codecov has a baseline for PR | |
| # coverage comparisons. | |
| if [[ "${EVENT_NAME}" == "push" ]]; then | |
| echo 'matrix=[{"name":"Test (Thread Sanitizer)","check":"test-tsan","runner":"macos-26","xcodebuild_flags":"-enableCodeCoverage YES -enableThreadSanitizer YES","result_bundle":"TestResults-TSAN","environment":"codecov"}]' >> "${GITHUB_OUTPUT}" | |
| exit 0 | |
| fi | |
| MATRIX='[{"name":"Conventional Commits","check":"commits","runner":"ubuntu-slim","fetch_depth":"0"}' | |
| # `edited` (title/body/base) also runs the full path-derived matrix. The | |
| # aggregate "conclusion" job is the only required status check, so it must | |
| # certify every relevant leg for the current commit. Collapsing to a | |
| # commits-only matrix on `edited` let a green run overwrite a prior failing | |
| # one on the same SHA, bypassing tests, lint-json, CodeQL and the rest. | |
| CHANGED=$(git diff --name-only "${BASE_SHA}...HEAD") | |
| # Swift, CI workflow, or project tooling changes: lint + sanitizer tests. | |
| # Tooling paths (scripts/, justfile, hooks, lint configs) are included so a | |
| # PR touching only those can't merge having run nothing but the commits leg. | |
| if echo "${CHANGED}" | grep -qE '\.swift$|^Package\.(swift|resolved)$|^macOSdb\.xcodeproj/|^\.swiftlint\.yml$|^\.github/workflows/ci\.yml$|^scripts/|^justfile$|^\.githooks/|^_typos\.toml$|^\.periphery\.yml$|^lychee\.toml$'; then | |
| MATRIX+=',{"name":"Lint","check":"lint","runner":"macos-26"}' | |
| MATRIX+=',{"name":"Test (Thread Sanitizer)","check":"test-tsan","runner":"macos-26","xcodebuild_flags":"-enableCodeCoverage YES -enableThreadSanitizer YES","result_bundle":"TestResults-TSAN","environment":"codecov"}' | |
| MATRIX+=',{"name":"Test (Address Sanitizer)","check":"test-asan","runner":"macos-26","xcodebuild_flags":"-enableAddressSanitizer YES","result_bundle":"TestResults-ASAN"}' | |
| fi | |
| # Source changes: CodeQL (excludes xcodeproj-only changes like version bumps) | |
| if echo "${CHANGED}" | grep -qE '^Sources/|^macOSdbApp/|^Package\.(swift|resolved)$'; then | |
| MATRIX+=',{"name":"CodeQL","check":"codeql","runner":"macos-26"}' | |
| fi | |
| # Data changes — and changes to the linter that gates them — run lint-json | |
| # so a modified scripts/lint-json.py is re-validated against existing data. | |
| if echo "${CHANGED}" | grep -qE '^data/|^scripts/'; then | |
| MATRIX+=',{"name":"Lint JSON","check":"lint-json","runner":"ubuntu-slim"}' | |
| fi | |
| # Site or data changes: format check + build | |
| if echo "${CHANGED}" | grep -qE '^site/|^data/'; then | |
| MATRIX+=',{"name":"Site","check":"site","runner":"ubuntu-slim"}' | |
| fi | |
| # Workflow changes: Actions security audit | |
| if echo "${CHANGED}" | grep -qE '^\.github/workflows/'; then | |
| MATRIX+=',{"name":"zizmor","check":"zizmor","runner":"ubuntu-latest"}' | |
| fi | |
| echo "matrix=${MATRIX}]" >> "${GITHUB_OUTPUT}" | |
| check: | |
| name: ${{ matrix.name }} | |
| needs: generate-matrix | |
| runs-on: ${{ matrix.runner }} | |
| environment: | |
| name: ${{ matrix.environment }} | |
| deployment: false | |
| permissions: | |
| contents: read | |
| pull-requests: read # required to fetch PR commits for conventional commit validation | |
| security-events: write # required for CodeQL and zizmor SARIF uploads | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: ${{ fromJson(needs.generate-matrix.outputs.matrix) }} | |
| steps: | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | |
| with: | |
| fetch-depth: ${{ matrix.fetch_depth || 1 }} | |
| persist-credentials: false | |
| # --- Conventional Commits --- | |
| - name: Check PR title | |
| if: matrix.check == 'commits' | |
| env: | |
| PR_TITLE: ${{ github.event.pull_request.title }} | |
| run: | | |
| PATTERN='^(feat|fix|docs|style|refactor|perf|test|build|ci|chore)(\(.+\))?: .+' | |
| if [[ ! "${PR_TITLE}" =~ ${PATTERN} ]]; then | |
| echo "::error::PR title '${PR_TITLE}' does not follow Conventional Commits." | |
| echo "" | |
| echo "Expected format: <type>(<scope>): <description>" | |
| echo "" | |
| echo "Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore" | |
| echo "" | |
| echo "Examples:" | |
| echo " feat(scanner): add Python component extraction" | |
| echo " fix(registry): correct M4 Ultra model identifier" | |
| echo " ci: add SwiftLint workflow" | |
| exit 1 | |
| fi | |
| - name: Check commit messages | |
| if: matrix.check == 'commits' | |
| env: | |
| BASE_SHA: ${{ github.event.pull_request.base.sha }} | |
| HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| run: | | |
| PATTERN='^(feat|fix|docs|style|refactor|perf|test|build|ci|chore)(\(.+\))?: .+' | |
| FAILED=0 | |
| while IFS= read -r LINE; do | |
| SHA="${LINE%% *}" | |
| MSG="${LINE#* }" | |
| if [[ "${MSG}" == Merge\ * ]]; then | |
| continue | |
| fi | |
| if [[ ! "${MSG}" =~ ${PATTERN} ]]; then | |
| echo "::error::Commit ${SHA} does not follow Conventional Commits: '${MSG}'" | |
| FAILED=1 | |
| fi | |
| done < <(git log --format="%h %s" "${BASE_SHA}..${HEAD_SHA}") | |
| if [[ "${FAILED}" -eq 1 ]]; then | |
| echo "" | |
| echo "All commit messages must follow: <type>(<scope>): <description>" | |
| echo "Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore" | |
| exit 1 | |
| fi | |
| # --- Lint --- | |
| - name: Install lint tools | |
| if: matrix.check == 'lint' | |
| env: | |
| HOMEBREW_NO_AUTO_UPDATE: 1 | |
| HOMEBREW_NO_ENV_HINTS: 1 | |
| run: brew install swiftlint typos-cli | |
| - name: SwiftLint | |
| if: matrix.check == 'lint' | |
| run: swiftlint --strict | |
| - name: Typos | |
| if: matrix.check == 'lint' | |
| run: typos | |
| # --- Lint JSON --- | |
| - name: Lint JSON | |
| if: matrix.check == 'lint-json' | |
| run: python3 scripts/lint-json.py | |
| # --- Site --- | |
| - name: Setup Node | |
| if: matrix.check == 'site' | |
| uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version: 26 | |
| - name: Install site dependencies | |
| if: matrix.check == 'site' | |
| working-directory: site | |
| # Fail closed on unreviewed install scripts (npm v12 default; see allowScripts in package.json). | |
| run: npm ci --strict-allow-scripts | |
| - name: Check formatting | |
| if: matrix.check == 'site' | |
| working-directory: site | |
| run: npm run format:check | |
| - name: Build site | |
| if: matrix.check == 'site' | |
| working-directory: site | |
| run: npm run build | |
| # --- Tests --- | |
| - name: Test | |
| if: startsWith(matrix.check, 'test-') | |
| env: | |
| XCODEBUILD_FLAGS: ${{ matrix.xcodebuild_flags }} | |
| RESULT_BUNDLE: ${{ matrix.result_bundle }} | |
| run: | | |
| xcodebuild test \ | |
| -workspace . \ | |
| -scheme macOSdb-Package \ | |
| -destination 'platform=macOS' \ | |
| -derivedDataPath ./DerivedData \ | |
| ${XCODEBUILD_FLAGS} \ | |
| -resultBundlePath "${RESULT_BUNDLE}.xcresult" \ | |
| CODE_SIGN_IDENTITY="" \ | |
| CODE_SIGNING_REQUIRED=NO \ | |
| CODE_SIGNING_ALLOWED=NO \ | |
| EXCLUDED_ARCHS=x86_64 | |
| - name: Coverage Summary | |
| if: always() && matrix.check == 'test-tsan' | |
| run: xcrun xccov view --report --only-targets TestResults-TSAN.xcresult || true | |
| - name: Export LCOV for Codecov | |
| if: success() && matrix.check == 'test-tsan' | |
| run: | | |
| PROFDATA=$(find ./DerivedData -name 'Coverage.profdata' -type f | head -1) | |
| if [[ -z "${PROFDATA}" ]]; then | |
| echo "::error::No Coverage.profdata found under ./DerivedData" | |
| exit 1 | |
| fi | |
| BINARY_ARGS=() | |
| FIRST="" | |
| while IFS= read -r xctest; do | |
| name=$(basename "${xctest}" .xctest) | |
| bin="${xctest}/Contents/MacOS/${name}" | |
| [[ -f "${bin}" ]] || continue | |
| if [[ -z "${FIRST}" ]]; then FIRST="${bin}"; else BINARY_ARGS+=(-object "${bin}"); fi | |
| done < <(find ./DerivedData/Build/Products -name '*.xctest' -type d) | |
| if [[ -z "${FIRST}" ]]; then | |
| echo "::error::No xctest binaries found under ./DerivedData/Build/Products" | |
| exit 1 | |
| fi | |
| xcrun llvm-cov export -format=lcov \ | |
| -ignore-filename-regex='(Tests/|\.build/|DerivedData/|/Checkouts/|/SourcePackages/)' \ | |
| "${FIRST}" \ | |
| ${BINARY_ARGS[@]+"${BINARY_ARGS[@]}"} \ | |
| -instr-profile="${PROFDATA}" \ | |
| > coverage.lcov | |
| echo "lcov: $(wc -l < coverage.lcov) lines" | |
| - name: Upload coverage to Codecov | |
| if: success() && matrix.check == 'test-tsan' | |
| uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| files: coverage.lcov | |
| fail_ci_if_error: false | |
| - name: Convert xcresult to JUnit | |
| if: ${{ !cancelled() && matrix.check == 'test-tsan' }} | |
| env: | |
| RESULT_BUNDLE: ${{ matrix.result_bundle }} | |
| run: python3 scripts/xcresult-to-junit.py "${RESULT_BUNDLE}.xcresult" > junit.xml | |
| - name: Upload test results to Codecov | |
| if: ${{ !cancelled() && matrix.check == 'test-tsan' }} | |
| uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| files: junit.xml | |
| fail_ci_if_error: false | |
| report_type: test_results | |
| - name: Upload Test Results | |
| if: always() && startsWith(matrix.check, 'test-') | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: ${{ matrix.result_bundle }} | |
| path: ${{ matrix.result_bundle }}.xcresult | |
| retention-days: 14 | |
| # --- CodeQL --- | |
| - name: Initialize CodeQL | |
| if: matrix.check == 'codeql' | |
| uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 | |
| with: | |
| languages: swift | |
| build-mode: manual | |
| - name: Build for CodeQL | |
| if: matrix.check == 'codeql' | |
| run: | | |
| xcodebuild \ | |
| -project macOSdb.xcodeproj \ | |
| -scheme macOSdb \ | |
| -destination 'generic/platform=macOS' \ | |
| -configuration Debug \ | |
| CODE_SIGN_IDENTITY="" \ | |
| CODE_SIGNING_REQUIRED=NO \ | |
| CODE_SIGNING_ALLOWED=NO \ | |
| EXCLUDED_ARCHS=x86_64 \ | |
| build | |
| - name: CodeQL Analysis | |
| if: matrix.check == 'codeql' | |
| uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 | |
| with: | |
| category: "/language:swift" | |
| # --- zizmor --- | |
| - name: Run zizmor | |
| if: matrix.check == 'zizmor' | |
| uses: zizmorcore/zizmor-action@5f14fd08f7cf1cb1609c1e344975f152c7ee938d # v0.5.6 | |
| with: | |
| persona: auditor | |
| conclusion: | |
| name: conclusion | |
| needs: check | |
| runs-on: ubuntu-slim | |
| if: always() | |
| steps: | |
| - name: Result | |
| env: | |
| CHECK_RESULT: ${{ needs.check.result }} | |
| run: test "${CHECK_RESULT}" = "success" |