Skip to content

Commit e1ce6a5

Browse files
authored
Merge pull request #12763 from github/repo-sync
repo sync
2 parents 8ed9291 + dcb4a5c commit e1ce6a5

9 files changed

Lines changed: 70 additions & 26 deletions

File tree

.github/actions-scripts/purge-fastly-edge-cache.js

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,4 @@
22

33
import purgeEdgeCache from '../../script/deployment/purge-edge-cache.js'
44

5-
try {
6-
await purgeEdgeCache()
7-
} catch (error) {
8-
console.error(`Failed to purge the edge cache: ${error.message}`)
9-
console.error(error)
10-
throw error
11-
}
5+
await purgeEdgeCache()

.github/workflows/browser-test.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,11 @@ jobs:
5555
path: .next/cache
5656
key: ${{ runner.os }}-nextjs-${{ hashFiles('package*.json') }}-${{ hashFiles('.github/workflows/browser-test.yml') }}
5757

58+
- name: Cache lib/redirects/.redirects-cache_en_ja.json
59+
uses: actions/cache@c64c572235d810460d0d6876e9c705ad5002b353
60+
with:
61+
path: lib/redirects/.redirects-cache_en_ja.json
62+
key: ${{ runner.os }}-redirects-cache-${{ hashFiles('.github/workflows/browser-test.yml') }}
63+
5864
- name: Run browser-test
5965
run: npm run browser-test

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ jobs:
178178
env:
179179
FASTLY_TOKEN: ${{ secrets.FASTLY_TOKEN }}
180180
FASTLY_SERVICE_ID: ${{ secrets.FASTLY_SERVICE_ID }}
181-
FASTLY_SURROGATE_KEY: 'all-the-things'
181+
FASTLY_SURROGATE_KEY: 'every-deployment'
182182
run: .github/actions-scripts/purge-fastly-edge-cache.js
183183

184184
- name: Send Slack notification if workflow failed

middleware/archived-enterprise-versions.js

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
import patterns from '../lib/patterns.js'
1010
import versionSatisfiesRange from '../lib/version-satisfies-range.js'
1111
import isArchivedVersion from '../lib/is-archived-version.js'
12+
import { setFastlySurrogateKey, SURROGATE_ENUMS } from './set-fastly-surrogate-key.js'
1213
import got from 'got'
1314
import { readCompressedJsonFileFallback } from '../lib/read-json-file.js'
1415
import { cacheControlFactory } from './cache-control.js'
@@ -55,6 +56,25 @@ const archivedFrontmatterFallbacks = readJsonFileLazily(
5556

5657
const cacheControl = cacheControlFactory(60 * 60 * 24 * 365)
5758

59+
// Combine all the things you need to make sure the response is
60+
// aggresively cached.
61+
const cacheAggressively = (res) => {
62+
cacheControl(res)
63+
64+
// This sets a custom Fastly surrogate key so that this response
65+
// won't get updated in every deployment.
66+
// Essentially, this sets a surrogate key such that Fastly
67+
// doesn't do soft-purges on these responses on every
68+
// automated deployment.
69+
setFastlySurrogateKey(res, SURROGATE_ENUMS.MANUAL)
70+
71+
// Because this middleware has (quite possibly) been executed before
72+
// the CSRF middleware, that would have set a cookie. Remove that.
73+
// The reason for removing the 'Set-Cookie' header is because
74+
// otherwise Fastly won't cache it.
75+
res.removeHeader('set-cookie')
76+
}
77+
5878
// The way `got` does retries:
5979
//
6080
// sleep = 1000 * Math.pow(2, retry - 1) + Math.random() * 100
@@ -119,7 +139,7 @@ export default async function archivedEnterpriseVersions(req, res, next) {
119139
// and memoized so calling it is cheap.
120140
const redirect = archivedRedirects()[req.path]
121141
if (redirect && redirect !== req.path) {
122-
cacheControl(res)
142+
cacheAggressively(res)
123143
return res.redirect(redirectCode, redirect)
124144
}
125145
}
@@ -138,7 +158,7 @@ export default async function archivedEnterpriseVersions(req, res, next) {
138158
// make redirects found via redirects.json redirect with a 301
139159
if (redirectJson[req.path]) {
140160
res.set('x-robots-tag', 'noindex')
141-
cacheControl(res)
161+
cacheAggressively(res)
142162
return res.redirect(redirectCode, redirectJson[req.path])
143163
}
144164
}
@@ -160,11 +180,14 @@ export default async function archivedEnterpriseVersions(req, res, next) {
160180
// make stubbed redirect files (which exist in versions <2.13) redirect with a 301
161181
const staticRedirect = r.body.match(patterns.staticRedirect)
162182
if (staticRedirect) {
163-
cacheControl(res)
183+
cacheAggressively(res)
164184
return res.redirect(redirectCode, staticRedirect[1])
165185
}
166186

167187
res.set('content-type', r.headers['content-type'])
188+
189+
cacheAggressively(res)
190+
168191
return res.send(r.body)
169192
}
170193

@@ -181,7 +204,7 @@ export default async function archivedEnterpriseVersions(req, res, next) {
181204
`fallback:${fallbackRedirect}`,
182205
])()
183206
if (r.statusCode === 200) {
184-
cacheControl(res)
207+
cacheAggressively(res)
185208
return res.redirect(redirectCode, fallbackRedirect)
186209
}
187210
}

middleware/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import csrf from './csrf.js'
1414
import handleCsrfErrors from './handle-csrf-errors.js'
1515
import compression from 'compression'
1616
import disableCachingOnSafari from './disable-caching-on-safari.js'
17-
import setFastlySurrogateKey from './set-fastly-surrogate-key.js'
17+
import setDefaultFastlySurrogateKey from './set-fastly-surrogate-key.js'
1818
import setFastlyCacheHeaders from './set-fastly-cache-headers.js'
1919
import catchBadAcceptLanguage from './catch-bad-accept-language.js'
2020
import reqUtils from './req-utils.js'
@@ -84,7 +84,7 @@ export default function (app) {
8484
// Must appear before static assets and all other requests
8585
// otherwise we won't be able to benefit from that functionality
8686
// for static assets as well.
87-
app.use(setFastlySurrogateKey)
87+
app.use(setDefaultFastlySurrogateKey)
8888

8989
// Must come before `csrf` otherwise you get a Set-Cookie on successful
9090
// asset requests. And it can come before `rateLimit` because if it's a
Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,29 @@
1-
export default function setFastlySurrogateKey(req, res, next) {
2-
// Fastly provides a Soft Purge feature that allows you to mark content as outdated (stale) instead of permanently
3-
// purging and thereby deleting it from Fastly's caches. Objects invalidated with Soft Purge will be treated as
4-
// outdated (stale) while Fastly fetches a new version from origin.
5-
//
6-
// Use of a surrogate key is required for soft purging
7-
// https://docs.fastly.com/en/guides/soft-purges
8-
// https://docs.fastly.com/en/guides/getting-started-with-surrogate-keys
9-
res.set('surrogate-key', 'all-the-things')
1+
// Fastly provides a Soft Purge feature that allows you to mark content as outdated (stale) instead of permanently
2+
// purging and thereby deleting it from Fastly's caches. Objects invalidated with Soft Purge will be treated as
3+
// outdated (stale) while Fastly fetches a new version from origin.
4+
//
5+
// Use of a surrogate key is required for soft purging
6+
// https://docs.fastly.com/en/guides/soft-purges
7+
// https://docs.fastly.com/en/guides/getting-started-with-surrogate-keys
108

9+
// What the header needs to be called for Fastly to recognize it.
10+
const KEY = 'surrogate-key'
11+
12+
export const SURROGATE_ENUMS = {
13+
DEFAULT: 'every-deployment',
14+
MANUAL: 'manual-purge',
15+
}
16+
17+
export function setFastlySurrogateKey(res, enumKey) {
18+
if (!Object.values(SURROGATE_ENUMS).includes(enumKey)) {
19+
throw new Error(
20+
`Unrecognizes surrogate enumKey. ${enumKey} is not one of ${Object.values(SURROGATE_ENUMS)}`
21+
)
22+
}
23+
res.set(KEY, enumKey)
24+
}
25+
26+
export default function setDefaultFastlySurrogateKey(req, res, next) {
27+
res.set(KEY, SURROGATE_ENUMS.DEFAULT)
1128
return next()
1229
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@
194194
"repository": "https://github.com/github/docs",
195195
"scripts": {
196196
"browser-test": "start-server-and-test browser-test-server 4001 browser-test-tests",
197-
"browser-test-server": "cross-env NODE_ENV=production WEB_CONCURRENCY=1 PORT=4001 node server.mjs",
197+
"browser-test-server": "cross-env NODE_ENV=production WEB_CONCURRENCY=1 PORT=4001 ENABLED_LANGUAGES=en,ja node server.mjs",
198198
"browser-test-tests": "cross-env BROWSER=1 NODE_OPTIONS=--experimental-vm-modules jest tests/browser/browser.js",
199199
"build": "next build",
200200
"debug": "cross-env NODE_ENV=development ENABLED_LANGUAGES='en,ja' nodemon --inspect server.mjs",

tests/rendering/server.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { describeViaActionsOnly } from '../helpers/conditional-runs.js'
55
import { loadPages } from '../../lib/page-data.js'
66
import CspParse from 'csp-parse'
77
import { productMap } from '../../lib/all-products.js'
8+
import { SURROGATE_ENUMS } from '../../middleware/set-fastly-surrogate-key.js'
89
import { jest } from '@jest/globals'
910

1011
const AZURE_STORAGE_URL = 'githubdocs.azureedge.net'
@@ -137,7 +138,7 @@ describe('server', () => {
137138
const res = await get('/en')
138139
expect(res.headers['cache-control']).toBe('private, no-store')
139140
expect(res.headers['surrogate-control']).toBe('private, no-store')
140-
expect(res.headers['surrogate-key']).toBe('all-the-things')
141+
expect(res.headers['surrogate-key']).toBe(SURROGATE_ENUMS.DEFAULT)
141142
})
142143

143144
test('does not render duplicate <html> or <body> tags', async () => {

tests/routing/deprecated-enterprise-versions.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import createApp from '../../lib/app.js'
22
import enterpriseServerReleases from '../../lib/enterprise-server-releases.js'
33
import { get, getDOM } from '../helpers/supertest.js'
4+
import { SURROGATE_ENUMS } from '../../middleware/set-fastly-surrogate-key.js'
45
import supertest from 'supertest'
56
import { jest } from '@jest/globals'
67

@@ -54,10 +55,12 @@ describe('enterprise deprecation', () => {
5455
expect($('h1').text()).toBe('About branches')
5556
})
5657

57-
test('sets the expected x-robots-tag header for deprecated Enterprise pages', async () => {
58+
test('sets the expected headers for deprecated Enterprise pages', async () => {
5859
const res = await get('/en/enterprise/2.13/user/articles/about-branches')
5960
expect(res.statusCode).toBe(200)
6061
expect(res.get('x-robots-tag')).toBe('noindex')
62+
expect(res.get('surrogate-key')).toBe(SURROGATE_ENUMS.MANUAL)
63+
expect(res.get('set-cookie')).toBeUndefined()
6164
})
6265

6366
test('handles requests for deprecated Enterprise pages ( <2.13 )', async () => {

0 commit comments

Comments
 (0)