-
Notifications
You must be signed in to change notification settings - Fork 35
260 lines (222 loc) · 9.55 KB
/
deploy.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
name: Deploy
##############################################################################
# WARNING!
# The deploy workflow (re-)uses information retrieved from the original
# commit which triggered the workflow, such as the branch name, the committer,
# and the commit message.
#
# This type of data should always be regarded as **untrusted** input and when
# these `github....` variables are used directly within the `run` context,
# they can lead to script injection and unintended execution of commands.
#
# To mitigate the risk of these type of script injection attacks, untrusted
# data is first set as a step-specific interim environment variable and only
# after that the environment variable (not the github variables directly)
# is used in the `run` context.
#
# This complies with the current best practices regarding defending against
# these type of attacks as per January 2022.
# For more information, see:
# https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions
##############################################################################
on:
push:
# Trigger the workflow on select branches.
branches:
- trunk
- 'release/**'
- 'hotfix/[0-9]+.[0-9]+*'
- 'feature/**'
# Trigger the workflow whenever a new tag is created.
tags:
- '**'
# Allow manually triggering the workflow.
workflow_dispatch:
# Cancels all previous workflow runs for the same branch that have not yet completed.
concurrency:
# The concurrency group contains the workflow name and the branch name.
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
DIST_ORG: 'Yoast-dist'
DIST_DEFAULT_BRANCH: 'main'
jobs:
prepare:
name: "Prepare the artifact"
# Don't run on forks.
if: github.repository_owner == 'Yoast'
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install PHP
uses: shivammathur/setup-php@v2
with:
php-version: 7.2
coverage: none
# This action also handles the caching of the Yarn dependencies.
# https://github.com/actions/setup-node
- name: Set up node and enable caching of dependencies
uses: actions/setup-node@v4
with:
node-version: '14'
cache: 'yarn'
- name: "Debug info: show tooling versions"
run: |
php -v
node --version
npm --version
yarn --version
grunt --version
git --version
# Install dependencies and handle caching in one go.
# The Grunt artifact creation will run `composer install` multiple times (both no-dev as well as dev),
# however, Composer packages downloaded are not cached via Grunt.
# Running `composer install` ahead of time will ensure that the cache is warmed up
# and available across runs of the same workflow.
# @link https://github.com/marketplace/actions/install-php-dependencies-with-composer
- name: Install Composer dependencies
uses: ramsey/composer-install@v3
with:
# Bust the cache at least once a month - output format: YYYY-MM.
custom-cache-suffix: $(date -u "+%Y-%m")
- name: Yarn install
run: yarn install
- name: "Grunt: set package version (tags only)"
if: ${{ github.event_name == 'push' && github.ref_type == 'tag' }}
env:
REF_NAME: ${{ github.ref_name }}
run: grunt set-version -new-version="$REF_NAME"
- name: "Grunt: update package version (tags only)"
if: ${{ github.event_name == 'push' && github.ref_type == 'tag' }}
run: grunt update-version
- name: "Grunt: create artifact"
run: grunt artifact
- name: "Copy composer.json"
run: cp composer.json ./artifact
- name: "Debug info: show contents of artifacts directory"
run: tree -aC ./artifact
- name: "Debug info: check git status"
run: git status -b -v -u
# Retention is normally 90 days, but this artifact is only for review
# and use in the next step, so no need to keep it for more than a day.
- name: Upload the artifact folder
uses: actions/upload-artifact@v4
if: ${{ success() }}
with:
name: deploy-artifact
path: ./artifact
if-no-files-found: error
retention-days: 1
deploy:
name: "Deploy to dist"
# Don't run on forks.
if: github.repository_owner == 'Yoast'
needs: prepare
runs-on: ubuntu-latest
steps:
- name: "Set variable: short sha"
id: set_sha
env:
SHA: ${{ github.sha }}
run: |
shortsha=$(echo "$SHA" | cut -b 1-6)
echo "SHORTSHA=$shortsha" >> $GITHUB_OUTPUT
- name: "Set variables: target branch, commit title"
id: set_vars
env:
REF_NAME: ${{ github.ref_name }}
run: |
if [[ "${{ github.event_name }}" == 'push' && "${{ github.ref_type }}" == 'branch' && "$REF_NAME" != "${{ env.DIST_DEFAULT_BRANCH }}" ]]; then
echo "BRANCH=$REF_NAME" >> $GITHUB_OUTPUT
echo "TITLE=Syncing branch $REF_NAME (sha: ${{ steps.set_sha.outputs.SHORTSHA }})" >> $GITHUB_OUTPUT
elif [[ "${{ github.event_name }}" == 'workflow_dispatch' && "$REF_NAME" != "${{ env.DIST_DEFAULT_BRANCH }}" ]]; then
echo "BRANCH=$REF_NAME" >> $GITHUB_OUTPUT
echo "TITLE=Manual deploy for $REF_NAME (sha: ${{ steps.set_sha.outputs.SHORTSHA }})" >> $GITHUB_OUTPUT
else # = Pushed tag.
echo "BRANCH=${{ env.DIST_DEFAULT_BRANCH }}" >> $GITHUB_OUTPUT
echo "TITLE=Release $REF_NAME" >> $GITHUB_OUTPUT
fi
- name: Checkout Yoast Dist repo
uses: actions/checkout@v4
with:
repository: ${{ env.DIST_ORG }}/${{ github.event.repository.name }}
ref: ${{ env.DIST_DEFAULT_BRANCH }}
# Personal Access Token for (push) access to the dist version of the repo.
token: ${{ secrets.YOASTBOT_CI_PAT_DIST }}
fetch-depth: 0
- name: "Create branch/Switch to branch"
if: ${{ steps.set_vars.outputs.BRANCH != env.DIST_DEFAULT_BRANCH }}
run: git checkout ${{ steps.set_vars.outputs.BRANCH }} 2>/dev/null || git checkout -b ${{ steps.set_vars.outputs.BRANCH }}
# Clean out all files to make sure that deleted files will actually
# be deleted when the artifact gets put in place.
- name: Remove all files
run: |
# Enable extended pattern matching.
shopt -s extglob
# Remove everything, except the ".git" directory.
rm -vrf !(.git/*)
# Disable extended pattern matching.
shopt -u extglob
# After the previous step, only the `.git` directory and its contents should remain.
- name: "Debug info: show contents of root directory after cleaning"
run: tree -aC .
# The artifact will be unpacked into the root directory of the repository.
- name: Download and unpack the prepared artifact
uses: actions/download-artifact@v4
with:
name: deploy-artifact
# Remove the vendor directory from the artifact, composer will generate it's own autoload.
- name: Remove generated vendor directory
run: rm -vrf ./vendor
- name: "Debug info: show contents of root directory after artifact insertion"
run: tree -aC .
- name: "Debug info: check git status"
run: git status -b -v -u
- name: Set Git config
env:
ACTOR: ${{ github.actor }}
run: |
git config user.name 'GitHub Action'
git config user.email "$ACTOR@users.noreply.github.com"
- name: Stage files
run: git add -A
- name: "Commit the files (branch)"
if: ${{ github.event_name != 'push' || github.ref_type != 'tag' }}
env:
COMMITTER: ${{ github.event.head_commit.committer.username }}
COMMIT_MSG: ${{ github.event.head_commit.message }}
COMMIT_URL: ${{ github.event.head_commit.url }}
COMMIT_TIME: ${{ github.event.head_commit.timestamp }}
run: |
git commit --allow-empty -m "${{ steps.set_vars.outputs.TITLE }}" \
-m "Synced up to commit hash: $COMMIT_URL" \
-m "Timestamp last commit: $COMMIT_TIME" \
-m "Committer last commit: @$COMMITTER" \
-m "" \
-m "Commit message last commit:" \
-m "---------------------------" \
-m "$COMMIT_MSG"
- name: "Commit the files (release)"
if: ${{ github.event_name == 'push' && github.ref_type == 'tag' }}
env:
COMMITTER: ${{ github.event.head_commit.committer.username }}
COMMIT_MSG: ${{ github.event.head_commit.message }}
COMMIT_URL: ${{ github.event.head_commit.url }}
COMMIT_TIME: ${{ github.event.head_commit.timestamp }}
run: |
git commit -m "${{ steps.set_vars.outputs.TITLE }}" \
-m "Commit hash for tag: $COMMIT_URL" \
-m "Timestamp for tag: $COMMIT_TIME" \
-m "Committer for tag: @$COMMITTER" \
-m "" \
-m "Commit message last commit:" \
-m "---------------------------" \
-m "$COMMIT_MSG"
- name: "Tag the commit (releases only)"
if: ${{ github.event_name == 'push' && github.ref_type == 'tag' }}
env:
REF_NAME: ${{ github.ref_name }}
run: git tag "$REF_NAME" $(git rev-parse HEAD)
- name: Push to target branch
run: git push -u origin ${{ steps.set_vars.outputs.BRANCH }} --tags -v