.github/workflows/pages.yml (4516B)
1 name: Deploy site
2
3 on:
4 push:
5 branches: [main]
6 schedule:
7 # Fetch distribution security data again every 6 hours.
8 - cron: '17 */6 * * *'
9 workflow_dispatch:
10
11 permissions:
12 contents: read
13
14 # One run at a time, including its data commit. A newer run waits; it is never cancelled midway.
15 concurrency:
16 group: pages
17 cancel-in-progress: false
18
19 # The site is built, tested and deployed from exactly the commit this run checked out, plus
20 # freshly fetched data. Recording that data in git is a separate, last job: it never pulls new
21 # code into the build, and a rejected push can never hold back a deploy.
22 jobs:
23 build:
24 runs-on: ubuntu-latest
25 permissions:
26 contents: read
27 pages: read
28 outputs:
29 data_changed: ${{ steps.data.outputs.changed }}
30 steps:
31 - uses: actions/checkout@v4
32 with:
33 persist-credentials: false
34
35 - uses: actions/setup-node@v4
36 with:
37 node-version: 22
38
39 # The same command as ci.yml.
40 - name: Test
41 run: npm test
42
43 # If the fixed versions in the official advisories differ from upstream.json, fail here and do not deploy.
44 - name: Update distro data
45 id: data
46 run: |
47 node tools/update-distro-data.mjs
48 if git diff --quiet -- site/data/distro.json; then
49 echo "changed=false" >> "$GITHUB_OUTPUT"
50 else
51 echo "changed=true" >> "$GITHUB_OUTPUT"
52 fi
53 env:
54 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
55
56 # The verdict tests above use a frozen copy of the data; this checks the data just fetched before it is
57 # deployed or committed.
58 - name: Check the fetched data
59 run: node --test test/data.test.mjs
60
61 - name: Assemble site
62 run: node tools/build-site.mjs
63
64 - uses: actions/configure-pages@v5
65
66 - uses: actions/upload-pages-artifact@v3
67 with:
68 path: _site
69
70 - name: Keep the new distro.json for the data commit
71 if: steps.data.outputs.changed == 'true'
72 uses: actions/upload-artifact@v4
73 with:
74 name: distro-data
75 path: site/data/distro.json
76 if-no-files-found: error
77 retention-days: 1
78 overwrite: true
79
80 deploy:
81 needs: build
82 runs-on: ubuntu-latest
83 permissions:
84 pages: write
85 id-token: write
86 environment:
87 name: github-pages
88 url: ${{ steps.deployment.outputs.page_url }}
89 steps:
90 - id: deployment
91 uses: actions/deploy-pages@v4
92
93 # Commit the data that is now live to main, so the history of distro.json is the history of
94 # the deployed data, and the next run starts from it. Runs only after a successful deploy.
95 commit-data:
96 needs: [build, deploy]
97 if: needs.build.outputs.data_changed == 'true' && github.ref == 'refs/heads/main'
98 runs-on: ubuntu-latest
99 permissions:
100 contents: write
101 steps:
102 # The latest main, not this run's commit: main may have moved on while this run waited or ran.
103 - uses: actions/checkout@v4
104 with:
105 ref: main
106
107 - uses: actions/download-artifact@v4
108 with:
109 name: distro-data
110 path: ${{ runner.temp }}/distro-data
111
112 - name: Commit distro.json
113 env:
114 NEW_DATA: ${{ runner.temp }}/distro-data/distro.json
115 run: |
116 # Compare without updated_at, so a main that already holds the same data is left alone.
117 strip() { jq -S 'del(.updated_at)' "$1"; }
118 if [ -f site/data/distro.json ] && [ "$(strip "$NEW_DATA")" = "$(strip site/data/distro.json)" ]; then
119 echo "main already has this data"
120 exit 0
121 fi
122 cp "$NEW_DATA" site/data/distro.json
123 git config user.name "github-actions[bot]"
124 git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
125 git add site/data/distro.json
126 git commit -m "data: update distro advisories"
127 # No pull and no retry: if main moved on again, or a rule on main blocks pushes from
128 # workflows, the deployed site is still current and the next run fetches and commits again.
129 if ! git push origin HEAD:main; then
130 echo "::warning title=Data commit not pushed::The new distro.json is deployed but was not pushed to main. The next run fetches the data again and retries. If a ruleset or branch protection on main blocks pushes from workflows, see the README section on self-hosting."
131 fi