-
Notifications
You must be signed in to change notification settings - Fork 48
200 lines (176 loc) · 6.71 KB
/
ci.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
name: CI
on:
push:
branches:
- master
pull_request:
workflow_dispatch:
inputs:
heroku-app:
description: Deploy to Heroku app (if set)
type: string
required: false
# Only one run per branch at a time.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
defaults:
run:
# This is the same as GitHub Action's `bash` keyword as of 20 June 2023:
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsshell
#
# Completely spelling it out here so that GitHub can't change it out from under us
# and we don't have to refer to the docs to know the expected behavior.
shell: bash --noprofile --norc -eo pipefail {0}
jobs:
# Lint regardless of build or test status and lint early.
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: 'package.json'
- run: node --version
- run: npm ci
- run: npm run lint:server
- run: npm run lint:static-site
- run: node ./scripts/check-resource-index-match.js
# Build into Heroku slug so we can deploy the same build that we test.
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: ./scripts/heroku-build
- if: always()
uses: actions/upload-artifact@v4
with:
name: build
path: |
build/slug.tar.gz
build/slug.tar.gz.sha256sum
build/slug.json
# Run tests in Heroku runtime environment against our built slug.
test:
if: github.repository == 'nextstrain/nextstrain.org'
needs: build
runs-on: ubuntu-latest
container:
image: heroku/heroku:22
env:
# Override NODE_ENV=production default in production build (slug)
NODE_ENV: development
# Set up Heroku runtime environment. See bash(1) or
# <https://www.gnu.org/software/bash/manual/bash.html#Invoked-non_002dinteractively>.
BASH_ENV: .heroku/BASH_ENV
steps:
- uses: actions/download-artifact@v4
with:
name: build
path: build/
- run: sha256sum --check build/slug.tar.gz.sha256sum
- run: tar --extract --file build/slug.tar.gz --xform 's,^[.]/app/,,'
- run: node --version
# (Re-)install dev deps which got pruned from production build (slug)
- run: npm ci
# configure AWS to run dev server necessary for `npm run test:ci`
- uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: ${{ vars.AWS_DEFAULT_REGION }}
aws-access-key-id: ${{ secrets.DEV_SERVER_AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.DEV_SERVER_AWS_SECRET_ACCESS_KEY }}
- run: npm run test:ci
env:
# Tests make GitHub API requests which are rate limited.
# Use the GitHub Actions token for a limit of 1,000 requests per hour.
# <https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api#primary-rate-limit-for-github_token-in-github-actions>
GITHUB_TOKEN: ${{ github.token }}
- if: always()
uses: actions/upload-artifact@v4
with:
name: test-logs
path: test/server.log
index-resources:
if: |2
github.repository == 'nextstrain/nextstrain.org'
&& github.event_name == 'push'
&& github.ref == 'refs/heads/master'
needs: test
permissions:
id-token: write # needed to interact with GitHub's OIDC Token endpoint
contents: read
uses: ./.github/workflows/index-resources.yml
secrets: inherit
deploy:
if: |2
!cancelled()
&& needs.build.result == 'success'
&& needs.test.result == 'success'
&& contains(fromJSON('["success", "skipped"]'), needs.index-resources.result)
&& github.repository == 'nextstrain/nextstrain.org'
&& ( (github.event_name == 'push' && github.ref == 'refs/heads/master')
|| (github.event_name == 'workflow_dispatch' && inputs.heroku-app) )
# Wait for "build", "test", and "index-resources" jobs above to pass.
needs:
- build
- test
- index-resources
# Name a GitHub environment configuration¹ to auto-create deployment
# records in GitHub based on this job's progress/status. Also grants
# access to environment-specific secrets.
#
# The URL is specific to this deployment, not the environment (i.e. an
# environment have deployments at different URLs).
#
# ¹ https://github.com/nextstrain/nextstrain.org/settings/environments
environment:
name: ${{ inputs.heroku-app || 'nextstrain-canary' }}
url: ${{ inputs.heroku-app && format('https://{0}.herokuapp.com', inputs.heroku-app) || 'https://next.nextstrain.org' }}
# Deploy steps
runs-on: ubuntu-latest
env:
HEROKU_APP: ${{ inputs.heroku-app || 'nextstrain-canary' }}
steps:
- uses: actions/download-artifact@v4
with:
name: build
path: build/
- name: Login to Heroku
run: echo "machine api.heroku.com login $HEROKU_USER password $HEROKU_TOKEN" >> ~/.netrc
env:
HEROKU_USER: "${{ vars.HEROKU_USER }}"
HEROKU_TOKEN: "${{ secrets.HEROKU_TOKEN }}"
- name: Upload slug
run: |
# <https://devcenter.heroku.com/articles/platform-api-reference#slug-create>
curl https://api.heroku.com/apps/"$HEROKU_APP"/slugs \
--data-binary @build/slug.json \
--header 'Content-Type: application/json' \
--header 'Accept: application/vnd.heroku+json; version=3' \
--fail --silent --show-error --location --netrc \
| tee slug.json
curl "$(jq -r .blob.url slug.json)" \
--request "$(jq -r .blob.method slug.json | tr a-z A-Z)" \
--header "Content-Type:" \
--data-binary @build/slug.tar.gz \
--fail --location --netrc \
| cat
- name: Release slug
run: |
# <https://devcenter.heroku.com/articles/platform-api-reference#release-create>
curl https://api.heroku.com/apps/"$HEROKU_APP"/releases \
--data-binary @<(jq '{slug: .id}' slug.json) \
--header 'Content-Type: application/json' \
--header 'Accept: application/vnd.heroku+json; version=3' \
--fail --silent --show-error --location --netrc \
| tee release.json
- if: always()
uses: actions/upload-artifact@v4
with:
name: deploy
path: |
slug.json
release.json
- if: always()
name: Logout of Heroku
run: sed -i -e '/^machine api\.heroku\.com/d' ~/.netrc