From fdb9e169c96d425aefb233837c6f3c6d5869bf13 Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Mon, 6 Jul 2026 10:35:28 +1000 Subject: [PATCH 1/2] Migrate GH Pages deploy from gh-pages branch to artifacts Replace peaceiris/actions-gh-pages with native GitHub Pages deployment (configure-pages / upload-pages-artifact / deploy-pages) and update the linkcheck workflow to download the release HTML archive instead of checking out the gh-pages branch. - publish.yml: add permissions (contents/actions/statuses/pages/id-token), concurrency group, and the github-pages environment; write CNAME into the build output; keep Netlify, release-asset upload, and notebook sync untouched - linkcheck.yml: download the latest release .tar.gz and run the QuantEcon AI link-checker instead of lychee against a gh-pages checkout Part of QuantEcon/meta#282 Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/linkcheck.yml | 41 ++++++++++++++++++--------------- .github/workflows/publish.yml | 32 ++++++++++++++++++++----- 2 files changed, 48 insertions(+), 25 deletions(-) diff --git a/.github/workflows/linkcheck.yml b/.github/workflows/linkcheck.yml index 78eb0ec8..5d882c2b 100644 --- a/.github/workflows/linkcheck.yml +++ b/.github/workflows/linkcheck.yml @@ -6,26 +6,29 @@ on: workflow_dispatch: jobs: link-checking: - name: Link Checking + name: QuantEcon AI link checking runs-on: "ubuntu-latest" permissions: - issues: write # required for peter-evans/create-issue-from-file + issues: write # required for QuantEcon link-checker steps: - # Checkout the live site (html) - - name: Checkout - uses: actions/checkout@v7 + # Download the latest release HTML archive (permanent, not subject to artifact expiry) + - name: Get latest release asset URL + id: release + env: + GH_TOKEN: ${{ github.token }} + run: | + ASSET_URL=$(gh api repos/${{ github.repository }}/releases/latest \ + --jq '.assets[] | select(.name | endswith(".tar.gz")) | .browser_download_url') + echo "asset-url=$ASSET_URL" >> $GITHUB_OUTPUT + - name: Download and extract release HTML + run: | + mkdir -p _site + curl -sL "${{ steps.release.outputs.asset-url }}" | tar -xz -C _site + - name: AI-Powered Link Checker + uses: QuantEcon/action-link-checker@main with: - ref: gh-pages - - name: Link Checker - id: lychee - uses: lycheeverse/lychee-action@v2 - with: - fail: false - args: --accept 200..=299,403,503 --base-url https://intro.quantecon.org *.html - - name: Create Issue From File - if: steps.lychee.outputs.exit_code != 0 - uses: peter-evans/create-issue-from-file@v6 - with: - title: Link Checker Report - content-filepath: ./lychee/out.md - labels: report, automated issue, linkchecker + html-path: '_site' + fail-on-broken: 'false' + silent-codes: '403,503' + ai-suggestions: 'true' + create-issue: 'true' diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index fc3e5361..59d9f4c3 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,12 +1,27 @@ -name: Build & Publish to GH-PAGES +name: Build & Publish to GH Pages on: push: tags: - 'publish*' + +permissions: + contents: write # upload release assets; Netlify commit comment + actions: read # dawidd6 download-artifact reads cache.yml's build-cache + statuses: write # Netlify commit status + pages: write # deploy to GitHub Pages + id-token: write # OIDC token for actions/deploy-pages + +concurrency: + group: "pages" + cancel-in-progress: false + jobs: publish: if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags') runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} steps: - name: Checkout uses: actions/checkout@v7 @@ -110,12 +125,17 @@ jobs: env: NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} - - name: Deploy website to gh-pages - uses: peaceiris/actions-gh-pages@v4 + - name: Add CNAME for custom domain + run: echo "intro.quantecon.org" > _build/html/CNAME + - name: Setup Pages + uses: actions/configure-pages@v6 + - name: Upload Pages artifact + uses: actions/upload-pages-artifact@v5 with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: _build/html/ - cname: intro.quantecon.org + path: _build/html/ + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v5 - name: Upload "_build" folder (cache) uses: actions/upload-artifact@v7 with: From 51c25b5170cb2f080f65429ef617ba188d6b6517 Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Mon, 6 Jul 2026 10:47:35 +1000 Subject: [PATCH 2/2] linkcheck: harden release-asset download (Copilot review) - add contents:read so the gh api releases call works under a restrictive permissions block - set -euo pipefail; select a single .tar.gz asset and fail with a clear error when none is found - curl -fsSL so an HTTP error page fails the step instead of being piped into tar Keeps QuantEcon/action-link-checker@main (first-party org action; matches the reference in lecture-python-programming). Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/linkcheck.yml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/linkcheck.yml b/.github/workflows/linkcheck.yml index 5d882c2b..41041772 100644 --- a/.github/workflows/linkcheck.yml +++ b/.github/workflows/linkcheck.yml @@ -9,6 +9,7 @@ jobs: name: QuantEcon AI link checking runs-on: "ubuntu-latest" permissions: + contents: read # read latest release assets via gh api issues: write # required for QuantEcon link-checker steps: # Download the latest release HTML archive (permanent, not subject to artifact expiry) @@ -17,13 +18,19 @@ jobs: env: GH_TOKEN: ${{ github.token }} run: | + set -euo pipefail ASSET_URL=$(gh api repos/${{ github.repository }}/releases/latest \ - --jq '.assets[] | select(.name | endswith(".tar.gz")) | .browser_download_url') - echo "asset-url=$ASSET_URL" >> $GITHUB_OUTPUT + --jq '[.assets[] | select(.name | endswith(".tar.gz")) | .browser_download_url] | first // ""') + if [ -z "$ASSET_URL" ]; then + echo "::error::No .tar.gz asset found on the latest release" + exit 1 + fi + echo "asset-url=$ASSET_URL" >> "$GITHUB_OUTPUT" - name: Download and extract release HTML run: | + set -euo pipefail mkdir -p _site - curl -sL "${{ steps.release.outputs.asset-url }}" | tar -xz -C _site + curl -fsSL "${{ steps.release.outputs.asset-url }}" | tar -xz -C _site - name: AI-Powered Link Checker uses: QuantEcon/action-link-checker@main with: