Skip to content

Commit 23af250

Browse files
authored
Merge branch 'main' into update-old-script
2 parents c3e8c3f + bcd4e23 commit 23af250

29 files changed

+426
-218
lines changed

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Closes [issue link]
2424

2525
### Check off the following:
2626

27-
- [ ] I have reviewed my changes in staging (look for the **deploy-to-heroku** link in your pull request, then click **View deployment**).
27+
- [ ] I have reviewed my changes in staging (look for the latest deployment event in your pull request's timeline, then click **View deployment**).
2828
- [ ] For content changes, I have completed the [self-review checklist](https://github.com/github/docs/blob/main/CONTRIBUTING.md#self-review).
2929

3030
### Writer impact (This section is for GitHub staff members only):
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
name: Staging - Deploy PR
2+
3+
# **What it does**: To deploy PRs to a Heroku staging environment.
4+
# **Why we have it**: To deploy with high visibility in case of failures.
5+
# **Who does it impact**: All contributors.
6+
7+
on:
8+
pull_request:
9+
types:
10+
- opened
11+
- reopened
12+
- synchronize
13+
- unlocked
14+
15+
jobs:
16+
deploy:
17+
if: ${{ github.repository == 'github/docs-internal' || github.repository == 'github/docs' }}
18+
name: Deploy
19+
runs-on: ubuntu-latest
20+
timeout-minutes: 10
21+
concurrency:
22+
group: staging_${{ github.head_ref }}
23+
cancel-in-progress: true
24+
steps:
25+
- name: Check out repo
26+
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
27+
with:
28+
# Enables cloning the Early Access repo later with the relevant PAT
29+
persist-credentials: 'false'
30+
31+
- name: Setup node
32+
uses: actions/setup-node@c46424eee26de4078d34105d3de3cc4992202b1e
33+
with:
34+
node-version: 16.x
35+
36+
- name: Get npm cache directory
37+
id: npm-cache
38+
run: |
39+
echo "::set-output name=dir::$(npm config get cache)"
40+
41+
- name: Cache node modules
42+
uses: actions/cache@0781355a23dac32fd3bac414512f4b903437991a
43+
with:
44+
path: ${{ steps.npm-cache.outputs.dir }}
45+
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
46+
restore-keys: |
47+
${{ runner.os }}-node-
48+
49+
- name: Install dependencies
50+
run: npm ci
51+
52+
- name: Deploy
53+
uses: actions/github-script@2b34a689ec86a68d8ab9478298f91d5401337b7d
54+
env:
55+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
56+
HEROKU_API_TOKEN: ${{ secrets.HEROKU_API_TOKEN }}
57+
DOCUBOT_REPO_PAT: ${{ secrets.DOCUBOT_REPO_PAT }}
58+
HYDRO_ENDPOINT: ${{ secrets.HYDRO_ENDPOINT }}
59+
HYDRO_SECRET: ${{ secrets.HYDRO_SECRET }}
60+
with:
61+
script: |
62+
const { GITHUB_TOKEN, HEROKU_API_TOKEN } = process.env
63+
64+
// Exit if GitHub Actions PAT is not found
65+
if (!GITHUB_TOKEN) {
66+
throw new Error('You must supply a GITHUB_TOKEN environment variable!')
67+
}
68+
69+
// Exit if Heroku API token is not found
70+
if (!HEROKU_API_TOKEN) {
71+
throw new Error('You must supply a HEROKU_API_TOKEN environment variable!')
72+
}
73+
74+
const getOctokit = require('./script/helpers/github')
75+
const deployToStaging = require('./script/deployment/deploy-to-staging')
76+
77+
// This helper uses the `GITHUB_TOKEN` implicitly!
78+
// We're using our usual version of Octokit vs. the provided `github`
79+
// instance to avoid versioning discrepancies.
80+
const octokit = getOctokit()
81+
82+
try {
83+
await deployToStaging({
84+
herokuToken: HEROKU_API_TOKEN,
85+
octokit,
86+
pullRequest: context.payload.pull_request,
87+
runId: context.runId
88+
})
89+
} catch (error) {
90+
console.error(`Failed to deploy to staging: ${error.message}`)
91+
console.error(error)
92+
throw error
93+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
name: Staging - Undeploy PR
2+
3+
# **What it does**: To undeploy PRs from a Heroku staging environment, i.e. destroy the Heroku App.
4+
# **Why we have it**: To save money spent on deployments for closed PRs.
5+
# **Who does it impact**: All contributors.
6+
7+
on:
8+
pull_request:
9+
types:
10+
- closed
11+
- locked
12+
13+
jobs:
14+
undeploy:
15+
if: ${{ github.repository == 'github/docs-internal' || github.repository == 'github/docs' }}
16+
name: Undeploy
17+
runs-on: ubuntu-latest
18+
timeout-minutes: 2
19+
concurrency:
20+
group: staging_${{ github.head_ref }}
21+
cancel-in-progress: true
22+
steps:
23+
- name: Check out repo
24+
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
25+
with:
26+
# Enables cloning the Early Access repo later with the relevant PAT
27+
persist-credentials: 'false'
28+
29+
- name: Setup node
30+
uses: actions/setup-node@c46424eee26de4078d34105d3de3cc4992202b1e
31+
with:
32+
node-version: 16.x
33+
34+
- name: Get npm cache directory
35+
id: npm-cache
36+
run: |
37+
echo "::set-output name=dir::$(npm config get cache)"
38+
39+
- name: Cache node modules
40+
uses: actions/cache@0781355a23dac32fd3bac414512f4b903437991a
41+
with:
42+
path: ${{ steps.npm-cache.outputs.dir }}
43+
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
44+
restore-keys: |
45+
${{ runner.os }}-node-
46+
47+
- name: Install dependencies
48+
run: npm ci
49+
50+
- name: Undeploy
51+
uses: actions/github-script@2b34a689ec86a68d8ab9478298f91d5401337b7d
52+
env:
53+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
54+
HEROKU_API_TOKEN: ${{ secrets.HEROKU_API_TOKEN }}
55+
with:
56+
script: |
57+
const { GITHUB_TOKEN, HEROKU_API_TOKEN } = process.env
58+
59+
// Exit if GitHub Actions PAT is not found
60+
if (!GITHUB_TOKEN) {
61+
throw new Error('You must supply a GITHUB_TOKEN environment variable!')
62+
}
63+
64+
// Exit if Heroku API token is not found
65+
if (!HEROKU_API_TOKEN) {
66+
throw new Error('You must supply a HEROKU_API_TOKEN environment variable!')
67+
}
68+
69+
const getOctokit = require('./script/helpers/github')
70+
const undeployFromStaging = require('./script/deployment/undeploy-from-staging')
71+
72+
// This helper uses the `GITHUB_TOKEN` implicitly!
73+
// We're using our usual version of Octokit vs. the provided `github`
74+
// instance to avoid versioning discrepancies.
75+
const octokit = getOctokit()
76+
77+
try {
78+
await undeployFromStaging({
79+
herokuToken: HEROKU_API_TOKEN,
80+
octokit,
81+
pullRequest: context.payload.pull_request,
82+
runId: context.runId
83+
})
84+
} catch (error) {
85+
console.error(`Failed to undeploy from staging: ${error.message}`)
86+
console.error(error)
87+
throw error
88+
}

.github/workflows/workflow-lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,4 @@ jobs:
2626
- name: Run linter
2727
uses: cschleiden/actions-linter@0ff16d6ac5103cca6c92e6cbc922b646baaea5be
2828
with:
29-
workflows: '[".github/workflows/*.yml"]'
29+
workflows: '[".github/workflows/*.yml", "!.github/workflows/staging-deploy-pr.yml", "!.github/workflows/staging-undeploy-pr.yml"]'

components/Header.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export const Header = () => {
3434
style={{ zIndex: 2 }}
3535
>
3636
{/* desktop header */}
37-
<div className="d-none d-lg-flex flex-justify-end">
37+
<div className="d-none d-lg-flex flex-justify-end" data-testid="desktop-header">
3838
{showVersionPicker && (
3939
<div className="py-2 mr-4">
4040
<HomepageVersionPicker />
@@ -54,7 +54,7 @@ export const Header = () => {
5454
</div>
5555

5656
{/* mobile header */}
57-
<div className="d-lg-none">
57+
<div className="d-lg-none" data-testid="mobile-header">
5858
<div className="d-flex flex-justify-between">
5959
<div className="d-flex flex-items-center" id="github-logo-mobile" role="banner">
6060
<Link aria-hidden="true" tabIndex={-1} href={`/${router.locale}`}>
@@ -71,6 +71,7 @@ export const Header = () => {
7171

7272
<div>
7373
<ButtonOutline
74+
data-testid="mobile-menu-button"
7475
css
7576
onClick={() => setIsMenuOpen(!isMenuOpen)}
7677
aria-label="Navigation Menu"

components/LanguagePicker.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export const LanguagePicker = ({ variant }: Props) => {
3232
<Link
3333
key={lang.code}
3434
href={router.asPath}
35-
locale={lang.hreflang}
35+
locale={lang.code}
3636
className={cx(
3737
'd-block py-2',
3838
lang.code === router.locale
@@ -71,7 +71,7 @@ export const LanguagePicker = ({ variant }: Props) => {
7171
{langs.map((lang) => {
7272
return (
7373
<Dropdown.Item key={lang.code}>
74-
<Link href={router.asPath} locale={lang.hreflang}>
74+
<Link href={router.asPath} locale={lang.code}>
7575
{lang.nativeName ? (
7676
<>
7777
{lang.nativeName} ({lang.name})

components/Search.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { useTranslation } from 'components/hooks/useTranslation'
55
import { sendEvent, EventType } from '../javascripts/events'
66
import { useMainContext } from './context/MainContext'
77
import { useVersion } from 'components/hooks/useVersion'
8+
import cx from 'classnames'
89

910
type SearchResult = {
1011
url: string
@@ -193,8 +194,9 @@ export function Search({ isStandalone = false, updateSearchParams = true, childr
193194
<div className="ais-SearchBox">
194195
<form role="search" className="ais-SearchBox-form" noValidate onSubmit={preventRefresh}>
195196
<input
197+
data-testid="site-search-input"
196198
ref={inputRef}
197-
className={'ais-SearchBox-input' + (isStandalone || query ? ' js-open' : '')}
199+
className={cx('ais-SearchBox-input', isStandalone || query ? 'js-open' : '')}
198200
type="search"
199201
placeholder={t`placeholder`}
200202
/* eslint-disable-next-line jsx-a11y/no-autofocus */

components/SidebarNav.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ export const SidebarNav = () => {
5555
width: 280px;
5656
height: 100vh;
5757
flex-shrink: 0;
58+
padding-bottom: 32px;
5859
}
5960
`}
6061
</style>

components/context/MainContext.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ export const getMainContextFromRequest = (req: any): MainContextT => {
118118
currentProduct: req.context.productMap[req.context.currentProduct] || null,
119119
currentLayoutName: req.context.currentLayoutName,
120120
isHomepageVersion: req.context.currentVersion === 'homepage',
121-
error: req.context.error || '',
121+
error: req.context.error ? req.context.error.toString() : '',
122122
data: {
123123
ui: req.context.site.data.ui,
124124
reusables: {

components/context/ProductLandingContext.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ export const getFeaturedLinksFromReq = (req: any): Record<string, Array<Featured
7979
Object.entries(req.context.featuredLinks || {}).map(([key, entries]) => {
8080
return [
8181
key,
82-
(entries as Array<any> || []).map((entry: any) => ({
82+
((entries as Array<any>) || []).map((entry: any) => ({
8383
href: entry.href,
8484
title: entry.title,
8585
intro: entry.intro,
@@ -144,7 +144,7 @@ export const getProductLandingContextFromRequest = (req: any): ProductLandingCon
144144
? req.context.page.featuredLinks.popularHeading || req.context.site.data.ui.toc[key]
145145
: req.context.site.data.ui.toc[key],
146146
viewAllHref:
147-
key === 'guides' && !req.context.currentCategory && hasGuidesPage
147+
key === 'guides' && !req.context.currentCategory && hasGuidesPage
148148
? `${req.context.currentPath}/guides`
149149
: '',
150150
articles: links.map((link: any) => {

0 commit comments

Comments
 (0)