From f547bcb943b0786494a9d35a621e3c969233c683 Mon Sep 17 00:00:00 2001 From: cevheri Date: Sat, 27 Jun 2026 20:59:07 +0300 Subject: [PATCH 1/7] ci: add build-check workflow, gate Pages deploy on release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ci.yml (new): runs bun install --frozen-lockfile + bun run build on every PR and push to main. Verification only, no deploy. Catches build breakage (e.g. dependency bumps) before merge. Free/unlimited on this public repo. - deploy.yml: trigger changed from push:main -> release: published. Production deploys are now deliberate and versioned — publishing a GitHub release builds and deploys to Pages. workflow_dispatch retained for manual runs. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/ci.yml | 40 ++++++++++++++++++++++++++++++++++++ .github/workflows/deploy.yml | 6 ++++-- 2 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..fdd0069 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,40 @@ +name: CI + +# Build verification only — runs on PRs and pushes to main. +# Does NOT deploy. Production deploy is gated on publishing a release +# (see deploy.yml, triggered on `release: published`). +on: + pull_request: + push: + branches: [main] + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: 24 + + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version: latest + + - name: Install dependencies + run: bun install --frozen-lockfile + + - name: Build website + run: bun run build diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 4b57b9f..9244787 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,8 +1,10 @@ name: Deploy to GitHub Pages +# Production deploy is gated on publishing a GitHub release. +# Build verification on PRs / main pushes lives in ci.yml. on: - push: - branches: [main] + release: + types: [published] workflow_dispatch: permissions: From 61525a53cb2daaf066447212261f158ac22068c6 Mon Sep 17 00:00:00 2001 From: cevheri Date: Sat, 27 Jun 2026 21:00:05 +0300 Subject: [PATCH 2/7] chore: bump version to 0.5.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7441141..3cae027 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "libredb-studio-website", "type": "module", - "version": "0.5.0", + "version": "0.5.1", "scripts": { "dev": "astro dev", "build": "node scripts/sync-docker-compose.mjs && astro build", From c1da579fcf10b83a56128ba546366e29e6274611 Mon Sep 17 00:00:00 2001 From: cevheri Date: Sat, 27 Jun 2026 21:05:47 +0300 Subject: [PATCH 3/7] ci: pin Bun version via .bun-version instead of latest Addresses Copilot review: 'bun-version: latest' makes CI non-deterministic. Pin to 1.3.14 (current latest stable) in a .bun-version file; both ci.yml and deploy.yml read it via setup-bun's bun-version-file input. Single source of truth, also picked up by local bun tooling. Co-Authored-By: Claude Opus 4.8 (1M context) --- .bun-version | 1 + .github/workflows/ci.yml | 2 +- .github/workflows/deploy.yml | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 .bun-version diff --git a/.bun-version b/.bun-version new file mode 100644 index 0000000..085c0f2 --- /dev/null +++ b/.bun-version @@ -0,0 +1 @@ +1.3.14 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fdd0069..93b17ba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: - name: Setup Bun uses: oven-sh/setup-bun@v2 with: - bun-version: latest + bun-version-file: .bun-version - name: Install dependencies run: bun install --frozen-lockfile diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 9244787..01fe8e9 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -31,7 +31,7 @@ jobs: - name: Setup Bun uses: oven-sh/setup-bun@v2 with: - bun-version: latest + bun-version-file: .bun-version - name: Install dependencies run: bun install From 6a6bd9847fcd8936b5505c65920a97bfd97fa100 Mon Sep 17 00:00:00 2001 From: cevheri Date: Sat, 27 Jun 2026 21:08:04 +0300 Subject: [PATCH 4/7] ci: add job summaries to Actions runs Both workflows now write a markdown summary to $GITHUB_STEP_SUMMARY (shown on the run page): build job reports bun/node/astro versions + pages built; deploy job reports release tag + live site URL. Untrusted values (release tag, page url) passed via env vars, never interpolated into run commands. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/ci.yml | 15 +++++++++++++++ .github/workflows/deploy.yml | 31 +++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 93b17ba..0605828 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,3 +38,18 @@ jobs: - name: Build website run: bun run build + + - name: Job summary + if: always() + run: | + { + echo "## 🏗️ Build verification — \`${{ job.status }}\`" + echo "" + echo "| Item | Value |" + echo "| --- | --- |" + echo "| Bun | $(bun --version) |" + echo "| Node | $(node --version) |" + echo "| Astro | $(node -p "require('astro/package.json').version" 2>/dev/null || echo n/a) |" + echo "| Pages built | $(find dist -name '*.html' 2>/dev/null | wc -l | tr -d ' ') |" + echo "| Commit | \`${GITHUB_SHA::7}\` |" + } >> "$GITHUB_STEP_SUMMARY" diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 01fe8e9..3dabb18 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -39,6 +39,21 @@ jobs: - name: Build website run: bun run build + - name: Build summary + if: always() + run: | + { + echo "## 🏗️ Build — \`${{ job.status }}\`" + echo "" + echo "| Item | Value |" + echo "| --- | --- |" + echo "| Bun | $(bun --version) |" + echo "| Node | $(node --version) |" + echo "| Astro | $(node -p "require('astro/package.json').version" 2>/dev/null || echo n/a) |" + echo "| Pages built | $(find dist -name '*.html' 2>/dev/null | wc -l | tr -d ' ') |" + echo "| Commit | \`${GITHUB_SHA::7}\` |" + } >> "$GITHUB_STEP_SUMMARY" + - name: Upload artifact uses: actions/upload-pages-artifact@v5 with: @@ -54,3 +69,19 @@ jobs: - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v5 + + - name: Deploy summary + if: always() + env: + RELEASE_TAG: ${{ github.event.release.tag_name }} + PAGE_URL: ${{ steps.deployment.outputs.page_url }} + run: | + { + echo "## 🚀 Production deploy — \`${{ job.status }}\`" + echo "" + echo "| Item | Value |" + echo "| --- | --- |" + echo "| Release | ${RELEASE_TAG:-_manual dispatch_} |" + echo "| Site URL | ${PAGE_URL:-n/a} |" + echo "| Commit | \`${GITHUB_SHA::7}\` |" + } >> "$GITHUB_STEP_SUMMARY" From 1d58436785ffae6060d297faea1209e77014a901 Mon Sep 17 00:00:00 2001 From: cevheri Date: Sat, 27 Jun 2026 21:09:34 +0300 Subject: [PATCH 5/7] ci: freeze lockfile in deploy build too Addresses Copilot review: deploy used plain 'bun install', so the production dependency graph could differ from what CI verified (and could silently mutate bun.lock). Use --frozen-lockfile to match ci.yml and keep release deploys reproducible. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 3dabb18..f76d36e 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -34,7 +34,7 @@ jobs: bun-version-file: .bun-version - name: Install dependencies - run: bun install + run: bun install --frozen-lockfile - name: Build website run: bun run build From 61a63263fc933968ece3b3e2e088e8f5e1159275 Mon Sep 17 00:00:00 2001 From: cevheri Date: Sat, 27 Jun 2026 21:12:09 +0300 Subject: [PATCH 6/7] ci: pin all GitHub Actions to full commit SHAs Supply-chain hardening: tags are mutable and can be repointed to malicious code, so pin every action to its latest-stable release commit SHA (tag kept as a comment for readability and Dependabot updates). - actions/checkout -> v7.0.0 9c091bb - actions/setup-node -> v6.4.0 48b55a0 - oven-sh/setup-bun -> v2.2.0 0c5077e - actions/upload-pages-artifact -> v5.0.0 fc324d3 - actions/deploy-pages -> v5.0.0 cd2ce8f Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/ci.yml | 6 +++--- .github/workflows/deploy.yml | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0605828..d10bf14 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,15 +21,15 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Setup Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 24 - name: Setup Bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: bun-version-file: .bun-version diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index f76d36e..d9ab27b 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -21,15 +21,15 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Setup Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 24 - name: Setup Bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: bun-version-file: .bun-version @@ -55,7 +55,7 @@ jobs: } >> "$GITHUB_STEP_SUMMARY" - name: Upload artifact - uses: actions/upload-pages-artifact@v5 + uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0 with: path: ./dist @@ -68,7 +68,7 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v5 + uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0 - name: Deploy summary if: always() From e5405fa8bac8931e4a0548e581caa9115a3a1a4e Mon Sep 17 00:00:00 2001 From: cevheri Date: Sat, 27 Jun 2026 21:17:01 +0300 Subject: [PATCH 7/7] ci: make summary step robust, precompute values into variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses Copilot review on the summary step. The nested-double-quote $(node -p "...") inside echo "..." actually works in bash (command substitution is its own quoting context — CI confirmed the step succeeded), but it is fragile to read. Precompute bun/node/astro/pages into variables with fallbacks so the heredoc only interpolates plain vars. Guard the page count behind [ -d dist ] so the step stays exit-0 under 'set -eo pipefail' even when if: always() runs it after a failed build (no dist dir). Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/ci.yml | 13 +++++++++---- .github/workflows/deploy.yml | 13 +++++++++---- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d10bf14..47276db 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,14 +42,19 @@ jobs: - name: Job summary if: always() run: | + bun_version=$(bun --version 2>/dev/null || echo n/a) + node_version=$(node --version 2>/dev/null || echo n/a) + astro_version=$(node -p "require('astro/package.json').version" 2>/dev/null || echo n/a) + pages_built=0 + [ -d dist ] && pages_built=$(find dist -name '*.html' | wc -l | tr -d ' ') { echo "## 🏗️ Build verification — \`${{ job.status }}\`" echo "" echo "| Item | Value |" echo "| --- | --- |" - echo "| Bun | $(bun --version) |" - echo "| Node | $(node --version) |" - echo "| Astro | $(node -p "require('astro/package.json').version" 2>/dev/null || echo n/a) |" - echo "| Pages built | $(find dist -name '*.html' 2>/dev/null | wc -l | tr -d ' ') |" + echo "| Bun | $bun_version |" + echo "| Node | $node_version |" + echo "| Astro | $astro_version |" + echo "| Pages built | $pages_built |" echo "| Commit | \`${GITHUB_SHA::7}\` |" } >> "$GITHUB_STEP_SUMMARY" diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index d9ab27b..2910baf 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -42,15 +42,20 @@ jobs: - name: Build summary if: always() run: | + bun_version=$(bun --version 2>/dev/null || echo n/a) + node_version=$(node --version 2>/dev/null || echo n/a) + astro_version=$(node -p "require('astro/package.json').version" 2>/dev/null || echo n/a) + pages_built=0 + [ -d dist ] && pages_built=$(find dist -name '*.html' | wc -l | tr -d ' ') { echo "## 🏗️ Build — \`${{ job.status }}\`" echo "" echo "| Item | Value |" echo "| --- | --- |" - echo "| Bun | $(bun --version) |" - echo "| Node | $(node --version) |" - echo "| Astro | $(node -p "require('astro/package.json').version" 2>/dev/null || echo n/a) |" - echo "| Pages built | $(find dist -name '*.html' 2>/dev/null | wc -l | tr -d ' ') |" + echo "| Bun | $bun_version |" + echo "| Node | $node_version |" + echo "| Astro | $astro_version |" + echo "| Pages built | $pages_built |" echo "| Commit | \`${GITHUB_SHA::7}\` |" } >> "$GITHUB_STEP_SUMMARY"