Skip to content

Commit cb79a7a

Browse files
author
Jonathan Visser
committed
Revise workflows based on correct security standards
1 parent 5646171 commit cb79a7a

7 files changed

Lines changed: 220 additions & 84 deletions

File tree

.github/workflows/cleanup_acceptance.yaml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
name: Cleanup acceptance environments
22

33
on:
4-
pull_request:
4+
pull_request_target:
55
types: [closed]
66

7+
permissions:
8+
contents: read
9+
710
jobs:
811
cleanup:
912
runs-on: ubuntu-latest
1013
container: quay.io/hypernode/deploy:latest-php8.4-node22
1114
environment: acceptance
15+
permissions:
16+
contents: read
1217
steps:
13-
- uses: actions/checkout@v2
14-
- name: Dump env
15-
run: env
18+
- uses: actions/checkout@v4
19+
with:
20+
ref: ${{ github.event.pull_request.base.sha }}
1621
- name: Cleanup acceptance environments
1722
run: hypernode-deploy cleanup acceptance -vvv
1823
env:

.github/workflows/deploy.yaml

Lines changed: 18 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,32 @@
1-
name: Deploy application
1+
name: Deploy to production
22

33
on:
4-
pull_request_target:
54
push:
65
branches:
76
- 'master'
87

9-
env:
10-
COMPOSER_CACHE_DIR: /tmp/composer-cache
8+
concurrency:
9+
group: production
10+
cancel-in-progress: false
11+
12+
permissions:
13+
contents: read
1114

1215
jobs:
1316
build:
1417
runs-on: ubuntu-latest
18+
timeout-minutes: 30
19+
permissions:
20+
contents: read
1521
container: quay.io/hypernode/deploy:latest-php8.4-node22
1622
steps:
17-
- uses: actions/checkout@v3
23+
- uses: actions/checkout@v4
1824
with:
25+
# updated_at.py reads the git log to render per-page timestamps.
1926
fetch-depth: 0
20-
ref: ${{ github.event.pull_request.head.sha || github.sha }}
21-
# Declares the repository safe and not under dubious ownership.
2227
- name: Add repository to git safe directories
2328
run: git config --global --add safe.directory $GITHUB_WORKSPACE
24-
- uses: actions/cache@v3
25-
with:
26-
path: /tmp/composer-cache
27-
key: ${{ runner.os }}-composer
28-
- uses: webfactory/ssh-agent@v0.7.0
29-
with:
30-
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
3129
- name: Set env for production build
32-
if: github.ref == 'refs/heads/master'
3330
run: |
3431
echo "DOCS_BASE_URL=https://docs.hypernode.com/" >> $GITHUB_ENV
3532
echo "DOCS_INDEX_FOLLOW=1" >> $GITHUB_ENV
@@ -41,78 +38,24 @@ jobs:
4138
path: build/build.tgz
4239
retention-days: 5
4340

44-
deploy_acceptance:
45-
needs: build
46-
runs-on: ubuntu-latest
47-
environment:
48-
name: acceptance
49-
url: ${{ steps.get_brancher_hostname.outputs.BRANCHER_URL }}
50-
if: github.event_name == 'pull_request_target'
51-
container: quay.io/hypernode/deploy:latest-php8.4-node22
52-
steps:
53-
- uses: actions/checkout@v3
54-
with:
55-
fetch-depth: 0
56-
ref: ${{ github.event.pull_request.head.sha || github.sha }}
57-
- name: download build artifact
58-
uses: actions/download-artifact@v4
59-
with:
60-
name: deployment-build
61-
path: build/
62-
- uses: webfactory/ssh-agent@v0.5.4
63-
with:
64-
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
65-
- run: mkdir -p $HOME/.ssh
66-
- name: deploy to acceptance
67-
run: hypernode-deploy deploy acceptance -vvv --reuse-brancher
68-
env:
69-
HYPERNODE_API_TOKEN: ${{ secrets.HYPERNODE_API_TOKEN }}
70-
- name: Get brancher hostname
71-
id: get_brancher_hostname
72-
run: echo "BRANCHER_URL=https://$(jq .hostnames[0] deployment-report.json -r)" >> $GITHUB_OUTPUT
73-
- name: Get changed pages
74-
id: changed_pages
75-
run: |
76-
git config --global --add safe.directory $(pwd)
77-
commits=${{ github.event.pull_request.commits }}
78-
if [[ -n "$commits" ]]; then
79-
# Prepare enough depth for diffs with target branch
80-
git fetch --depth="$(( commits + 1 ))"
81-
fi
82-
result="$(python3 ci/bin/get_changed_urls.py \
83-
${{ github.event.pull_request.base.sha }} \
84-
${{github.event.pull_request.head.sha}} \
85-
--base-url=${{ steps.get_brancher_hostname.outputs.BRANCHER_URL }}
86-
)"
87-
echo "$result"
88-
echo "CHANGED_PAGES<<EOF" >> $GITHUB_OUTPUT
89-
echo "$result" >> $GITHUB_OUTPUT
90-
echo "EOF" >> $GITHUB_OUTPUT
91-
shell: bash
92-
- name: Comment hostname on PR
93-
uses: thollander/actions-comment-pull-request@v1
94-
with:
95-
message: |
96-
Acceptance server is available at ${{ steps.get_brancher_hostname.outputs.BRANCHER_URL }}.
97-
${{ steps.changed_pages.outputs.CHANGED_PAGES }}
98-
9941
deploy_production:
10042
needs: build
10143
runs-on: ubuntu-latest
102-
concurrency: production
44+
timeout-minutes: 30
10345
environment:
10446
name: production
105-
url: https://docs.hypernode.io
106-
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
47+
url: https://docs.hypernode.com
48+
permissions:
49+
contents: read
10750
container: quay.io/hypernode/deploy:latest-php8.4-node22
10851
steps:
109-
- uses: actions/checkout@v3
52+
- uses: actions/checkout@v4
11053
- name: download build artifact
11154
uses: actions/download-artifact@v4
11255
with:
11356
name: deployment-build
11457
path: build/
115-
- uses: webfactory/ssh-agent@v0.5.4
58+
- uses: webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555 # v0.10.0
11659
with:
11760
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
11861
- run: mkdir -p $HOME/.ssh

.github/workflows/lint.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ on:
55

66
permissions:
77
contents: read
8-
pull-requests: write
98

109
jobs:
1110
test:
1211
runs-on: ubuntu-latest
12+
permissions:
13+
contents: read
14+
pull-requests: write
1315
strategy:
1416
matrix:
1517
python-version: ['3.12']
@@ -26,6 +28,6 @@ jobs:
2628
pip install -r requirements/base.txt
2729
- name: Check markdown format
2830
run: mdformat docs/
29-
- uses: parkerbxyz/suggest-changes@v2
31+
- uses: parkerbxyz/suggest-changes@e24c62a5a3235e6090721c7b0355b825a3a4ba9a # v3.1.2
3032
with:
3133
event: 'REQUEST_CHANGES'

.github/workflows/pr-build.yaml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Build pull request
2+
3+
on:
4+
pull_request:
5+
6+
permissions:
7+
contents: read
8+
9+
jobs:
10+
build:
11+
runs-on: ubuntu-latest
12+
permissions:
13+
contents: read
14+
container: quay.io/hypernode/deploy:latest-php8.4-node22
15+
steps:
16+
- uses: actions/checkout@v4
17+
with:
18+
fetch-depth: 0
19+
- name: Add repository to git safe directories
20+
run: git config --global --add safe.directory $GITHUB_WORKSPACE
21+
- run: hypernode-deploy build -vvv
22+
- name: archive build artifact
23+
uses: actions/upload-artifact@v4
24+
with:
25+
name: deployment-build
26+
path: build/build.tgz
27+
retention-days: 5

.github/workflows/pr-deploy.yaml

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
name: Deploy pull request to acceptance
2+
3+
on:
4+
workflow_run:
5+
workflows: ["Build pull request"]
6+
types: [completed]
7+
8+
permissions:
9+
contents: read
10+
11+
jobs:
12+
deploy_acceptance:
13+
if: >-
14+
github.event.workflow_run.event == 'pull_request' &&
15+
github.event.workflow_run.conclusion == 'success'
16+
runs-on: ubuntu-latest
17+
timeout-minutes: 30
18+
concurrency:
19+
group: acceptance-${{ github.event.workflow_run.head_repository.full_name }}-${{ github.event.workflow_run.head_branch }}
20+
cancel-in-progress: false
21+
environment:
22+
name: acceptance
23+
url: ${{ steps.get_brancher_hostname.outputs.BRANCHER_URL }}
24+
permissions:
25+
actions: read
26+
contents: read
27+
pull-requests: write
28+
statuses: write
29+
container: quay.io/hypernode/deploy:latest-php8.4-node22
30+
steps:
31+
- name: Resolve the pull request behind this build
32+
id: pr
33+
uses: actions/github-script@v7
34+
with:
35+
script: |
36+
const run = context.payload.workflow_run;
37+
38+
// Populated for same-repository branches, empty for forks.
39+
let number = (run.pull_requests || []).map((p) => p.number)[0];
40+
if (!number) {
41+
const { data: prs } =
42+
await github.rest.repos.listPullRequestsAssociatedWithCommit({
43+
owner: context.repo.owner,
44+
repo: context.repo.repo,
45+
commit_sha: run.head_sha,
46+
});
47+
number = prs.filter((p) => p.state === 'open').map((p) => p.number)[0];
48+
}
49+
if (!number) {
50+
core.setFailed(`No open pull request found for commit ${run.head_sha}`);
51+
return;
52+
}
53+
54+
const { data: pr } = await github.rest.pulls.get({
55+
owner: context.repo.owner,
56+
repo: context.repo.repo,
57+
pull_number: number,
58+
});
59+
core.setOutput('number', pr.number);
60+
core.setOutput('head_sha', run.head_sha);
61+
core.setOutput('head_ref', pr.head.ref);
62+
core.setOutput('base_sha', pr.base.sha);
63+
64+
- name: Check out the trusted deploy configuration
65+
uses: actions/checkout@v4
66+
with:
67+
ref: ${{ github.event.repository.default_branch }}
68+
fetch-depth: 0
69+
- name: Add repository to git safe directories
70+
run: git config --global --add safe.directory $GITHUB_WORKSPACE
71+
72+
- name: download build artifact
73+
uses: actions/download-artifact@v4
74+
with:
75+
name: deployment-build
76+
path: build/
77+
run-id: ${{ github.event.workflow_run.id }}
78+
github-token: ${{ secrets.GITHUB_TOKEN }}
79+
80+
- uses: webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555 # v0.10.0
81+
with:
82+
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
83+
- run: mkdir -p $HOME/.ssh
84+
85+
- name: deploy to acceptance
86+
run: hypernode-deploy deploy acceptance -vvv --reuse-brancher
87+
env:
88+
HYPERNODE_API_TOKEN: ${{ secrets.HYPERNODE_API_TOKEN }}
89+
# workflow_run does not set GITHUB_HEAD_REF, which deploy.php uses to
90+
# label the brancher. Without this every pull request shares one node.
91+
CI_REF: ${{ steps.pr.outputs.head_ref }}
92+
93+
- name: Get brancher hostname
94+
id: get_brancher_hostname
95+
run: echo "BRANCHER_URL=https://$(jq .hostnames[0] deployment-report.json -r)" >> $GITHUB_OUTPUT
96+
97+
- name: Get changed pages
98+
id: changed_pages
99+
env:
100+
BASE_SHA: ${{ steps.pr.outputs.base_sha }}
101+
HEAD_SHA: ${{ steps.pr.outputs.head_sha }}
102+
BRANCHER_URL: ${{ steps.get_brancher_hostname.outputs.BRANCHER_URL }}
103+
run: |
104+
# The built commit is fetched by SHA as data to diff against (the
105+
# pull request ref may already point at a newer push); it is never
106+
# checked out or executed.
107+
git fetch --no-tags --quiet origin "$HEAD_SHA"
108+
result="$(python3 ci/bin/get_changed_urls.py \
109+
"$BASE_SHA" \
110+
"$HEAD_SHA" \
111+
--base-url="$BRANCHER_URL"
112+
)"
113+
echo "$result"
114+
{
115+
echo "CHANGED_PAGES<<EOF"
116+
echo "$result"
117+
echo "EOF"
118+
} >> "$GITHUB_OUTPUT"
119+
shell: bash
120+
121+
- name: Comment hostname on PR
122+
uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b # v3.0.1
123+
with:
124+
pr-number: ${{ steps.pr.outputs.number }}
125+
comment-tag: acceptance-environment
126+
message: |
127+
Acceptance server is available at ${{ steps.get_brancher_hostname.outputs.BRANCHER_URL }}.
128+
${{ steps.changed_pages.outputs.CHANGED_PAGES }}
129+
130+
# workflow_run runs do not appear in the pull request's check list.
131+
- name: Mirror result onto the pull request head commit
132+
if: always() && steps.pr.outputs.head_sha
133+
uses: actions/github-script@v7
134+
env:
135+
HEAD_SHA: ${{ steps.pr.outputs.head_sha }}
136+
JOB_STATUS: ${{ job.status }}
137+
BRANCHER_URL: ${{ steps.get_brancher_hostname.outputs.BRANCHER_URL }}
138+
with:
139+
script: |
140+
const ok = process.env.JOB_STATUS === 'success';
141+
const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
142+
await github.rest.repos.createCommitStatus({
143+
owner: context.repo.owner,
144+
repo: context.repo.repo,
145+
sha: process.env.HEAD_SHA,
146+
state: ok ? 'success' : 'failure',
147+
context: 'Deploy pull request to acceptance',
148+
target_url: ok ? (process.env.BRANCHER_URL || runUrl) : runUrl,
149+
description: ok
150+
? 'Acceptance environment deployed'
151+
: 'Acceptance deploy failed',
152+
});

.github/workflows/test.yaml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,20 @@ name: Run tests
33
on:
44
pull_request:
55

6+
permissions:
7+
contents: read
8+
69
jobs:
710
test:
811
runs-on: ubuntu-latest
12+
timeout-minutes: 30
913
strategy:
1014
matrix:
1115
python-version: ['3.11', '3.12']
1216

1317
steps:
14-
- uses: actions/checkout@v3
15-
- uses: actions/setup-python@v4
18+
- uses: actions/checkout@v4
19+
- uses: actions/setup-python@v5
1620
with:
1721
python-version: ${{ matrix.python-version }}
1822
- name: Install dependencies

deploy.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,9 @@
142142

143143
$testingStage = $configuration->addStage("acceptance", "docs");
144144
$testingStage->addBrancherServer("docs")
145-
->setLabels(['stage=acceptance', 'ci_ref=' . (\getenv('GITHUB_HEAD_REF') ?: 'none')]);
145+
->setLabels([
146+
'stage=acceptance',
147+
'ci_ref=' . (\getenv('CI_REF') ?: \getenv('GITHUB_HEAD_REF') ?: 'none'),
148+
]);
146149

147150
return $configuration;

0 commit comments

Comments
 (0)