Skip to content

Commit 27dca15

Browse files
authored
Merge pull request #12984 from github/repo-sync
repo sync
2 parents 87a9280 + 586490e commit 27dca15

8 files changed

Lines changed: 304 additions & 118 deletions

File tree

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/usr/bin/env node
2+
3+
import getOctokit from '../../script/helpers/github.js'
4+
5+
const { GITHUB_TOKEN } = process.env
6+
7+
// Exit if GitHub Actions PAT is not found
8+
if (!GITHUB_TOKEN) {
9+
throw new Error('You must supply a GITHUB_TOKEN environment variable!')
10+
}
11+
12+
// This helper uses the `GITHUB_TOKEN` implicitly!
13+
// We're using our usual version of Octokit vs. the provided `github`
14+
// instance to avoid versioning discrepancies.
15+
const octokit = getOctokit()
16+
17+
const { CONTEXT_NAME, ACTIONS_RUN_LOG, HEAD_SHA } = process.env
18+
if (!CONTEXT_NAME) {
19+
throw new Error('$CONTEXT_NAME not set')
20+
}
21+
if (!ACTIONS_RUN_LOG) {
22+
throw new Error('$ACTIONS_RUN_LOG not set')
23+
}
24+
if (!HEAD_SHA) {
25+
throw new Error('$HEAD_SHA not set')
26+
}
27+
28+
await octokit.repos.createCommitStatus({
29+
owner,
30+
repo,
31+
sha: HEAD_SHA,
32+
context: CONTEXT_NAME,
33+
state: 'success',
34+
description: 'Successfully deployed! See logs.',
35+
target_url: ACTIONS_RUN_LOG,
36+
})

.github/actions-scripts/staging-deploy.js

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ if (!HEROKU_API_TOKEN) {
2121
// instance to avoid versioning discrepancies.
2222
const octokit = getOctokit()
2323

24-
const { RUN_ID, PR_URL, SOURCE_BLOB_URL, CONTEXT_NAME, ACTIONS_RUN_LOG, HEAD_SHA } = process.env
24+
const { RUN_ID, PR_URL, SOURCE_BLOB_URL } = process.env
2525
if (!RUN_ID) {
2626
throw new Error('$RUN_ID not set')
2727
}
@@ -31,15 +31,6 @@ if (!PR_URL) {
3131
if (!SOURCE_BLOB_URL) {
3232
throw new Error('$SOURCE_BLOB_URL not set')
3333
}
34-
if (!CONTEXT_NAME) {
35-
throw new Error('$CONTEXT_NAME not set')
36-
}
37-
if (!ACTIONS_RUN_LOG) {
38-
throw new Error('$ACTIONS_RUN_LOG not set')
39-
}
40-
if (!HEAD_SHA) {
41-
throw new Error('$HEAD_SHA not set')
42-
}
4334

4435
const { owner, repo, pullNumber } = parsePrUrl(PR_URL)
4536
if (!owner || !repo || !pullNumber) {
@@ -62,13 +53,3 @@ await deployToStaging({
6253
sourceBlobUrl: SOURCE_BLOB_URL,
6354
runId: RUN_ID,
6455
})
65-
66-
await octokit.repos.createCommitStatus({
67-
owner,
68-
repo,
69-
sha: HEAD_SHA,
70-
context: CONTEXT_NAME,
71-
state: 'success',
72-
description: 'Successfully deployed! See logs.',
73-
target_url: ACTIONS_RUN_LOG,
74-
})

.github/workflows/prod-build-deploy.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ jobs:
5252
DOCUBOT_REPO_PAT: ${{ secrets.DOCUBOT_REPO_PAT }}
5353
GIT_BRANCH: main
5454

55+
- name: Cache nextjs build
56+
uses: actions/cache@c64c572235d810460d0d6876e9c705ad5002b353
57+
with:
58+
path: .next/cache
59+
key: ${{ runner.os }}-nextjs-${{ hashFiles('package*.json') }}
60+
5561
- name: Build
5662
run: npm run build
5763

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
name: Staging - Build and Deploy PR (fast and private-only)
2+
3+
# **What it does**: Builds and deploys PRs to staging but ONLY for docs-internal
4+
# **Why we have it**: Most PRs are made on the private repo. Let's make those extra fast if we can worry less about security.
5+
# **Who does it impact**: All staff.
6+
7+
# This whole workflow is only guaranteed to be secure in the *private
8+
# repo* and because we repo-sync these files over the to the public one,
9+
# IT'S CRUCIALLY IMPORTANT THAT THIS WORKFLOW IS ONLY ENABLED IN docs-internal!
10+
11+
on:
12+
# Ideally, we'd like to use 'pull_request' because we can more easily
13+
# test changes to this workflow without relying on merges to 'main'.
14+
# But this is guaranteed to be safer and won't have the problem of
15+
# necessary secrets not being available.
16+
# Perhaps some day when we're confident this workflow will always
17+
# work in a regular PR, we can switch to that.
18+
pull_request_target:
19+
20+
permissions:
21+
actions: read
22+
contents: read
23+
deployments: write
24+
pull-requests: read
25+
statuses: write
26+
27+
# This allows one Build workflow run to interrupt another
28+
# These are different from the concurrency in that here it checks if the
29+
# whole workflow runs again. The "inner concurrency" is used for
30+
# undeployments to cleaning up resources.
31+
concurrency:
32+
group: '${{ github.workflow }} @ ${{ github.event.pull_request.head.label }}'
33+
cancel-in-progress: true
34+
35+
jobs:
36+
build-and-deploy:
37+
# Important. This whole file is only supposed to run in the PRIVATE repo.
38+
if: ${{ github.repository == 'github/docs-internal' }}
39+
40+
# The assumption here is that self-hosted is faster (e.g CPU power)
41+
# that the regular ones. And it matters in this workflow because
42+
# we do heavy CPU stuff with `npm run build` and `tar`
43+
# runs-on: ubuntu-latest
44+
runs-on: self-hosted
45+
46+
timeout-minutes: 5
47+
# This interrupts Build, Deploy, and pre-write Undeploy workflow runs in
48+
# progress for this PR branch.
49+
concurrency:
50+
group: 'PR Staging @ ${{ github.event.pull_request.head.label }}'
51+
cancel-in-progress: true
52+
steps:
53+
- name: Check out repo
54+
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
55+
with:
56+
ref: ${{ github.event.pull_request.head.sha }}
57+
lfs: 'true'
58+
# To prevent issues with cloning early access content later
59+
persist-credentials: 'false'
60+
61+
- name: Check out LFS objects
62+
run: git lfs checkout
63+
64+
- name: Setup node
65+
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
66+
with:
67+
node-version: 16.13.x
68+
cache: npm
69+
70+
- name: Install dependencies
71+
run: npm ci
72+
73+
- name: Cache nextjs build
74+
uses: actions/cache@c64c572235d810460d0d6876e9c705ad5002b353
75+
with:
76+
path: .next/cache
77+
key: ${{ runner.os }}-nextjs-${{ hashFiles('package*.json') }}
78+
79+
- name: Build
80+
run: npm run build
81+
82+
- name: Clone early access
83+
run: node script/early-access/clone-for-build.js
84+
env:
85+
DOCUBOT_REPO_PAT: ${{ secrets.DOCUBOT_REPO_PAT }}
86+
GIT_BRANCH: ${{ github.event.pull_request.head.sha }}
87+
88+
- name: Check that the PR isn't blocking deploys
89+
# We can't use ${{...}} on this if statement because of this bug
90+
# https://github.com/cschleiden/actions-linter/issues/114
91+
if: github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'automated-block-deploy')
92+
run: |
93+
echo "The PR appears to have the label 'automated-block-deploy'"
94+
echo "Will not proceed to deploy the PR."
95+
exit 2
96+
97+
- name: Create a Heroku build source
98+
id: build-source
99+
uses: actions/github-script@2b34a689ec86a68d8ab9478298f91d5401337b7d
100+
env:
101+
HEROKU_API_TOKEN: ${{ secrets.HEROKU_API_TOKEN }}
102+
with:
103+
script: |
104+
const { owner, repo } = context.repo
105+
106+
if (owner !== 'github') {
107+
throw new Error(`Repository owner must be 'github' but was: ${owner}`)
108+
}
109+
if (repo !== 'docs-internal') {
110+
throw new Error(`Repository name must be 'docs-internal' but was: ${repo}`)
111+
}
112+
113+
const Heroku = require('heroku-client')
114+
const heroku = new Heroku({ token: process.env.HEROKU_API_TOKEN })
115+
116+
try {
117+
const { source_blob: sourceBlob } = await heroku.post('/sources')
118+
const { put_url: uploadUrl, get_url: downloadUrl } = sourceBlob
119+
120+
core.setOutput('upload_url', uploadUrl)
121+
core.setOutput('download_url', downloadUrl)
122+
} catch (error) {
123+
if (error.statusCode === 503) {
124+
console.error('💀 Heroku may be down! Please check its Status page: https://status.heroku.com/')
125+
}
126+
throw error
127+
}
128+
129+
- name: Remove development-only dependencies
130+
run: npm prune --production
131+
132+
- name: Remove all npm scripts
133+
run: npm pkg delete scripts
134+
135+
- name: Set npm script for Heroku build to noop
136+
run: npm set-script heroku-postbuild "echo 'Application was pre-built!'"
137+
138+
- name: Delete heavy things we won't need deployed
139+
run: |
140+
141+
# The dereferenced file is not used in runtime once the
142+
# decorated file has been created from it.
143+
rm -rf lib/rest/static/dereferenced
144+
145+
# Translations are never tested in Staging builds
146+
# but let's keep the empty directory.
147+
rm -rf translations
148+
mkdir translations
149+
150+
# Delete all the big search indexes that are NOT English (`*-en-*`)
151+
pushd lib/search/indexes
152+
ls | grep -v '\-en\-' | xargs rm
153+
popd
154+
155+
# Note! Some day it would be nice to be able to delete
156+
# all the heavy assets because they bloat the tarball.
157+
# But it's not obvious how to test it then. For now, we'll have
158+
# to accept that every staging build has a copy of the images.
159+
160+
# The assumption here is that a staging build will not
161+
# need these legacy redirects. Only the redirects from
162+
# front-matter will be at play.
163+
# These static redirects json files are notoriously large
164+
# and they make the tarball unnecessarily large.
165+
echo '[]' > lib/redirects/static/archived-frontmatter-fallbacks.json
166+
echo '{}' > lib/redirects/static/developer.json
167+
echo '{}' > lib/redirects/static/archived-redirects-from-213-to-217.json
168+
169+
# This will turn every `lib/**/static/*.json` into
170+
# an equivalent `lib/**/static/*.json.br` file.
171+
# Once the server starts, it'll know to fall back to reading
172+
# the `.br` equivalent if the `.json` file isn't present.
173+
node .github/actions-scripts/compress-large-files.js
174+
175+
- name: Make the tarball for Heroku
176+
run: |
177+
# We can't delete the .next/cache directory from the workflow
178+
# because it's needed for caching, but we can at least exclude it
179+
# from the tarball. Then it can be cached but not weigh down the
180+
# tarball we intend to deploy.
181+
tar -zc --exclude=.next/cache --file=app.tar.gz \
182+
node_modules/ \
183+
.next/ \
184+
assets/ \
185+
content/ \
186+
data/ \
187+
includes/ \
188+
lib/ \
189+
middleware/ \
190+
translations/ \
191+
server.mjs \
192+
package*.json \
193+
.npmrc \
194+
feature-flags.json \
195+
next.config.js \
196+
app.json \
197+
Procfile
198+
199+
du -sh app.tar.gz
200+
201+
# See: https://devcenter.heroku.com/articles/build-and-release-using-the-api#sources-endpoint
202+
- name: Upload to the Heroku build source
203+
env:
204+
UPLOAD_URL: ${{ steps.build-source.outputs.upload_url }}
205+
run: |
206+
curl "$UPLOAD_URL" \
207+
-X PUT \
208+
-H 'Content-Type:' \
209+
--data-binary @app.tar.gz
210+
211+
# 'npm install' is faster than 'npm ci' because it only needs to
212+
# *append* what's missing from ./node_modules/
213+
- name: Re-install dependencies so we get devDependencies back
214+
run: npm install --no-audit --no-fund --only=dev
215+
216+
- name: Deploy
217+
id: deploy
218+
env:
219+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
220+
HEROKU_API_TOKEN: ${{ secrets.HEROKU_API_TOKEN }}
221+
HYDRO_ENDPOINT: ${{ secrets.HYDRO_ENDPOINT }}
222+
HYDRO_SECRET: ${{ secrets.HYDRO_SECRET }}
223+
PR_URL: ${{ github.event.pull_request.html_url }}
224+
SOURCE_BLOB_URL: ${{ steps.build-source.outputs.download_url }}
225+
ALLOWED_POLLING_FAILURES_PER_PHASE: '15'
226+
RUN_ID: ${{ github.run_id }}
227+
run: .github/actions-scripts/staging-deploy.js

.github/workflows/staging-build-pr.yml

Lines changed: 6 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ name: Staging - Build PR
44
# **Why we have it**: Because it's not safe to share our deploy secrets with forked repos: https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
55
# **Who does it impact**: All contributors.
66

7+
# IT'S CRUCIALLY IMPORTANT THAT THIS WORKFLOW IS ONLY ENABLED IN docs!
8+
79
on:
810
pull_request:
911
types:
@@ -31,7 +33,9 @@ concurrency:
3133

3234
jobs:
3335
build-pr:
34-
if: ${{ github.repository == 'github/docs-internal' || github.repository == 'github/docs' }}
36+
# Important. This whole file is only supposed to run in the PUBLIC repo.
37+
if: ${{ github.repository == 'github/docs' }}
38+
3539
runs-on: ${{ fromJSON('["ubuntu-latest", "self-hosted"]')[github.repository == 'github/docs-internal'] }}
3640
timeout-minutes: 5
3741
# This interrupts Build, Deploy, and pre-write Undeploy workflow runs in
@@ -45,7 +49,7 @@ jobs:
4549

4650
# Make sure only approved files are changed if it's in github/docs
4751
- name: Check changed files
48-
if: ${{ github.repository == 'github/docs' && github.event.pull_request.user.login != 'Octomerger' }}
52+
if: ${{ github.event.pull_request.user.login != 'Octomerger' }}
4953
uses: dorny/paths-filter@eb75a1edc117d3756a18ef89958ee59f9500ba58
5054
id: filter
5155
with:
@@ -107,44 +111,6 @@ jobs:
107111
- name: Set npm script for Heroku build to noop
108112
run: npm set-script heroku-postbuild "echo 'Application was pre-built!'"
109113

110-
- name: Delete heavy things we won't need deployed
111-
if: ${{ github.repository == 'github/docs-internal' }}
112-
run: |
113-
114-
# The dereferenced file is not used in runtime once the
115-
# decorated file has been created from it.
116-
rm -fr lib/rest/static/dereferenced
117-
118-
# Translations are never tested in Staging builds
119-
# but let's keep the empty directory.
120-
rm -fr translations
121-
mkdir translations
122-
123-
# Delete all the big search indexes that are NOT English (`*-en-*`)
124-
pushd lib/search/indexes
125-
ls | grep -v '\-en\-' | xargs rm
126-
popd
127-
128-
# Note! Some day it would be nice to be able to delete
129-
# all the heavy assets because they bloat the tarball.
130-
# But it's not obvious how to test it then. For now, we'll have
131-
# to accept that every staging build has a copy of the images.
132-
133-
# The assumption here is that a staging build will not
134-
# need these legacy redirects. Only the redirects from
135-
# front-matter will be at play.
136-
# These static redirects json files are notoriously large
137-
# and they make the tarball unnecessarily large.
138-
echo '[]' > lib/redirects/static/archived-frontmatter-fallbacks.json
139-
echo '{}' > lib/redirects/static/developer.json
140-
echo '{}' > lib/redirects/static/archived-redirects-from-213-to-217.json
141-
142-
# This will turn every `lib/**/static/*.json` into
143-
# an equivalent `lib/**/static/*.json.br` file.
144-
# Once the server starts, it'll know to fall back to reading
145-
# the `.br` equivalent if the `.json` file isn't present.
146-
node .github/actions-scripts/compress-large-files.js
147-
148114
- name: Create an archive
149115
# Only bother if this is actually a pull request
150116
if: ${{ github.event.pull_request.number }}

0 commit comments

Comments
 (0)