Skip to content

Commit 40d47a9

Browse files
authored
Merge branch 'main' into patch-2
2 parents d8bee07 + d08235b commit 40d47a9

File tree

7,207 files changed

+286900
-268983
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

7,207 files changed

+286900
-268983
lines changed

.devcontainer/Dockerfile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,8 @@ FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:0-${VARIANT}
1414

1515
# [Optional] Uncomment if you want to install more global node modules
1616
# RUN su node -c "npm install -g <your-package-list-here>"
17+
18+
# Install the GitHub CLI see:
19+
# https://github.com/microsoft/vscode-dev-containers/blob/3d59f9fe37edb68f78874620f33dac5a62ef2b93/script-library/docs/github.md
20+
COPY library-scripts/github-debian.sh /tmp/library-scripts/
21+
RUN apt-get update && bash /tmp/library-scripts/github-debian.sh

.devcontainer/devcontainer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
22
// https://github.com/microsoft/vscode-dev-containers/tree/v0.177.0/containers/javascript-node
3+
// -
34
{
45
"name": "docs.github.com",
56
"build": {
@@ -20,7 +21,6 @@
2021
"sissel.shopify-liquid",
2122
"davidanson.vscode-markdownlint",
2223
"bierner.markdown-preview-github-styles",
23-
"yzhang.markdown-all-in-one",
2424
"streetsidesoftware.code-spell-checker",
2525
"hubwriter.open-reusable"
2626
],
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#!/usr/bin/env bash
2+
#-------------------------------------------------------------------------------------------------------------
3+
# Copyright (c) Microsoft Corporation. All rights reserved.
4+
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
5+
#-------------------------------------------------------------------------------------------------------------
6+
#
7+
# Docs: https://github.com/microsoft/vscode-dev-containers/blob/master/script-library/docs/github.md
8+
#
9+
# Syntax: ./github-debian.sh [version]
10+
11+
CLI_VERSION=${1:-"latest"}
12+
13+
set -e
14+
15+
if [ "$(id -u)" -ne 0 ]; then
16+
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
17+
exit 1
18+
fi
19+
20+
export DEBIAN_FRONTEND=noninteractive
21+
22+
# Install curl, apt-transport-https or gpg if missing
23+
if ! dpkg -s curl ca-certificates > /dev/null 2>&1; then
24+
if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then
25+
apt-get update
26+
fi
27+
apt-get -y install --no-install-recommends curl ca-certificates
28+
fi
29+
30+
# Get latest release number if latest is specified
31+
if [ "${CLI_VERSION}" = "latest" ] || [ "${CLI_VERSION}" = "current" ] || [ "${CLI_VERSION}" = "lts" ]; then
32+
LATEST_RELEASE=$(curl -sSL -H "Accept: application/vnd.github.v3+json" "https://api.github.com/repos/cli/cli/releases?per_page=1&page=1")
33+
CLI_VERSION=$(echo ${LATEST_RELEASE} | grep -oE 'tag_name":\s*"v[^"]+' | sed -n '/tag_name":\s*"v/s///p')
34+
fi
35+
36+
# Install the GitHub CLI
37+
echo "Downloading github CLI..."
38+
curl -OsSL https://github.com/cli/cli/releases/download/v${CLI_VERSION}/gh_${CLI_VERSION}_linux_amd64.deb
39+
echo "Installing github CLI..."
40+
apt-get install ./gh_${CLI_VERSION}_linux_amd64.deb
41+
echo "Removing github CLI deb file after installation..."
42+
rm -rf ./gh_${CLI_VERSION}_linux_amd64.deb
43+
echo "Done!"

.dockerignore

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
.devcontainer/
2+
.git/
3+
.github/
4+
.vscode/
5+
contributing/
6+
docs/
7+
node_modules/
8+
script/
9+
tests/
10+
lib/rest/static/dereferenced
11+
# Folder is cloned during the preview + prod workflows, the assets are merged into other locations for use before the build
12+
docs-early-access/

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package-lock.json @github/docs-engineering
1717
package.json @github/docs-engineering
1818

1919
# Localization
20+
/.github/actions-scripts/create-translation-batch-pr.js @github/docs-localization
2021
/.github/workflows/create-translation-batch-pr.yml @github/docs-localization
2122
/.github/workflows/crowdin.yml @github/docs-localization
2223
/crowdin*.yml @github/docs-engineering @github/docs-localization

.github/actions-scripts/content-changes-table-comment.js

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,20 @@
11
#!/usr/bin/env node
22

3-
import createStagingAppName from '../../script/deployment/create-staging-app-name.js'
43
import * as github from '@actions/github'
54
import { setOutput } from '@actions/core'
65

6+
const { GITHUB_TOKEN, APP_URL } = process.env
77
const context = github.context
88

9-
const githubToken = process.env.GITHUB_TOKEN
10-
if (!githubToken) {
9+
if (!GITHUB_TOKEN) {
1110
throw new Error(`GITHUB_TOKEN environment variable not set`)
1211
}
1312

14-
const stagingPrefix = createStagingAppName({
15-
repo: context.payload.repository.name,
16-
pullNumber: context.payload.number,
17-
branch: context.payload.pull_request.head.ref,
18-
})
13+
if (!APP_URL) {
14+
throw new Error(`APP_URL environment variable not set`)
15+
}
1916

20-
const octokit = github.getOctokit(githubToken)
17+
const octokit = github.getOctokit(GITHUB_TOKEN)
2118

2219
const response = await octokit.rest.repos.compareCommits({
2320
owner: context.repo.owner,
@@ -29,7 +26,7 @@ const response = await octokit.rest.repos.compareCommits({
2926
const { files } = response.data
3027

3128
let markdownTable =
32-
'| **Source** | **Staging** | **Production** | **What Changed** |\n|:----------- |:----------- |:----------- |:----------- |\n'
29+
'| **Source** | **Preview** | **Production** | **What Changed** |\n|:----------- |:----------- |:----------- |:----------- |\n'
3330

3431
const pathPrefix = 'content/'
3532
const articleFiles = files.filter(
@@ -39,14 +36,14 @@ for (const file of articleFiles) {
3936
const sourceUrl = file.blob_url
4037
const fileName = file.filename.slice(pathPrefix.length)
4138
const fileUrl = fileName.slice(0, fileName.lastIndexOf('.'))
42-
const stagingLink = `https://${stagingPrefix}.herokuapp.com/${fileUrl}`
39+
const previewLink = `${APP_URL}/${fileUrl}`
4340
const productionLink = `https://docs.github.com/${fileUrl}`
4441
let markdownLine = ''
4542

4643
if (file.status === 'modified') {
47-
markdownLine = `| [content/${fileName}](${sourceUrl}) | [Modified](${stagingLink}) | [Original](${productionLink}) | |\n`
44+
markdownLine = `| [content/${fileName}](${sourceUrl}) | [Modified](${previewLink}) | [Original](${productionLink}) | |\n`
4845
} else if (file.status === 'added') {
49-
markdownLine = `| New file: [content/${fileName}](${sourceUrl}) | [Modified](${stagingLink}) | | |\n`
46+
markdownLine = `| New file: [content/${fileName}](${sourceUrl}) | [Modified](${previewLink}) | | |\n`
5047
}
5148
markdownTable += markdownLine
5249
}
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
#!/usr/bin/env node
2+
3+
import fs from 'fs'
4+
import github from '@actions/github'
5+
6+
const OPTIONS = Object.fromEntries(
7+
['BASE', 'BODY_FILE', 'GITHUB_TOKEN', 'HEAD', 'LANGUAGE', 'TITLE', 'GITHUB_REPOSITORY'].map(
8+
(envVarName) => {
9+
const envVarValue = process.env[envVarName]
10+
if (!envVarValue) {
11+
throw new Error(`You must supply a ${envVarName} environment variable`)
12+
}
13+
return [envVarName, envVarValue]
14+
}
15+
)
16+
)
17+
18+
if (!process.env.GITHUB_REPOSITORY) {
19+
throw new Error('GITHUB_REPOSITORY environment variable not set')
20+
}
21+
22+
const RETRY_STATUSES = [
23+
422, // Retry the operation if the PR already exists
24+
502, // Retry the operation if the API responds with a `502 Bad Gateway` error.
25+
]
26+
const RETRY_ATTEMPTS = 3
27+
const {
28+
// One of the default environment variables provided by Actions.
29+
GITHUB_REPOSITORY,
30+
31+
// These are passed in from the step in the workflow file.
32+
TITLE,
33+
BASE,
34+
HEAD,
35+
LANGUAGE,
36+
BODY_FILE,
37+
GITHUB_TOKEN,
38+
} = OPTIONS
39+
const [OWNER, REPO] = GITHUB_REPOSITORY.split('/')
40+
41+
const octokit = github.getOctokit(GITHUB_TOKEN)
42+
43+
/**
44+
* @param {object} config Configuration options for finding the PR.
45+
* @returns {Promise<number | undefined>} The PR number.
46+
*/
47+
async function findPullRequestNumber(config) {
48+
// Get a list of PRs and see if one already exists.
49+
const { data: listOfPullRequests } = await octokit.rest.pulls.list({
50+
owner: config.owner,
51+
repo: config.repo,
52+
head: `${config.owner}:${config.head}`,
53+
})
54+
55+
return listOfPullRequests[0]?.number
56+
}
57+
58+
/**
59+
* When this file was first created, we only introduced support for creating a pull request for some translation batch.
60+
* However, some of our first workflow runs failed during the pull request creation due to a timeout error.
61+
* There have been cases where, despite the timeout error, the pull request gets created _anyway_.
62+
* To accommodate this reality, we created this function to look for an existing pull request before a new one is created.
63+
* Although the "find" check is redundant in the first "cycle", it's designed this way to recursively call the function again via its retry mechanism should that be necessary.
64+
*
65+
* @param {object} config Configuration options for creating the pull request.
66+
* @returns {Promise<number>} The PR number.
67+
*/
68+
async function findOrCreatePullRequest(config) {
69+
const found = await findPullRequestNumber(config)
70+
71+
if (found) {
72+
return found
73+
}
74+
75+
try {
76+
const { data: pullRequest } = await octokit.rest.pulls.create({
77+
owner: config.owner,
78+
repo: config.repo,
79+
base: config.base,
80+
head: config.head,
81+
title: config.title,
82+
body: config.body,
83+
draft: false,
84+
})
85+
86+
return pullRequest.number
87+
} catch (error) {
88+
if (!error.response || !config.retryCount) {
89+
throw error
90+
}
91+
92+
if (!config.retryStatuses.includes(error.response.status)) {
93+
throw error
94+
}
95+
96+
console.error(`Error creating pull request: ${error.message}`)
97+
console.warn(`Retrying in 5 seconds...`)
98+
await new Promise((resolve) => setTimeout(resolve, 5000))
99+
100+
config.retryCount -= 1
101+
102+
return findOrCreatePullRequest(config)
103+
}
104+
}
105+
106+
/**
107+
* @param {object} config Configuration options for labeling the PR
108+
* @returns {Promise<undefined>}
109+
*/
110+
async function labelPullRequest(config) {
111+
await octokit.rest.issues.update({
112+
owner: config.owner,
113+
repo: config.repo,
114+
issue_number: config.issue_number,
115+
labels: config.labels,
116+
})
117+
}
118+
119+
async function main() {
120+
const options = {
121+
title: TITLE,
122+
base: BASE,
123+
head: HEAD,
124+
body: fs.readFileSync(BODY_FILE, 'utf8'),
125+
labels: ['translation-batch', `translation-batch-${LANGUAGE}`],
126+
owner: OWNER,
127+
repo: REPO,
128+
retryStatuses: RETRY_STATUSES,
129+
retryCount: RETRY_ATTEMPTS,
130+
}
131+
132+
options.issue_number = await findOrCreatePullRequest(options)
133+
const pr = `${GITHUB_REPOSITORY}#${options.issue_number}`
134+
console.log(`Created PR ${pr}`)
135+
136+
// metadata parameters aren't currently available in `github.rest.pulls.create`,
137+
// but they are in `github.rest.issues.update`.
138+
await labelPullRequest(options)
139+
console.log(`Updated ${pr} with these labels: ${options.labels.join(', ')}`)
140+
}
141+
142+
main()
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#!/usr/bin/env bash
2+
3+
# [start-readme]
4+
#
5+
# This script sets environment variables with info about the preview app for a given PR
6+
#
7+
# [end-readme]
8+
9+
# ENV VARS NEEDED TO RUN
10+
[[ -z $GITHUB_REPOSITORY ]] && { echo "Missing GITHUB_REPOSITORY. Exiting."; exit 1; }
11+
[[ -z $PR_NUMBER ]] && { echo "Missing PR_NUMBER. Exiting."; exit 1; }
12+
[[ -z $GITHUB_ENV ]] && { echo "Missing GITHUB_ENV. Exiting."; exit 1; }
13+
[[ -z $APP_NAME_SEED ]] && { echo "Missing APP_NAME_SEED. Exiting."; exit 1; }
14+
15+
PREVIEW_ENV_LOCATION="eastus"
16+
echo "PREVIEW_ENV_LOCATION=${PREVIEW_ENV_LOCATION}" >> $GITHUB_ENV
17+
18+
REPO_NAME="${GITHUB_REPOSITORY#*\/}"
19+
echo "REPO_NAME=${REPO_NAME}" >> $GITHUB_ENV
20+
21+
DEPLOYMENT_NAME="${REPO_NAME}-pr-${PR_NUMBER}"
22+
echo "DEPLOYMENT_NAME=${DEPLOYMENT_NAME}" >> $GITHUB_ENV
23+
24+
APP_NAME_BASE="${REPO_NAME}-preview-${PR_NUMBER}"
25+
echo "APP_NAME_BASE=${APP_NAME_BASE}" >> $GITHUB_ENV
26+
27+
# pseudo random string so guessing a preview env URL is more difficult
28+
APP_SHA=$(echo -n "${APP_NAME_SEED}-${APP_NAME_BASE}" | sha1sum | cut -c1-6)
29+
30+
APP_NAME="${APP_NAME_BASE}-${APP_SHA}"
31+
echo "APP_NAME=${APP_NAME}" >> $GITHUB_ENV
32+
33+
APP_URL="https://${APP_NAME}.${PREVIEW_ENV_LOCATION}.azurecontainer.io"
34+
echo "APP_URL=${APP_URL}" >> $GITHUB_ENV
35+
36+
IMAGE_REPO="${GITHUB_REPOSITORY}/pr-${PR_NUMBER}"
37+
echo "IMAGE_REPO=${IMAGE_REPO}" >> $GITHUB_ENV
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/usr/bin/env bash
2+
3+
# [start-readme]
4+
#
5+
# This script takes docs-early-access files and merges them into docs-internal
6+
#
7+
# [end-readme]
8+
9+
mv docs-early-access/assets/images assets/images/early-access
10+
mv docs-early-access/content content/early-access
11+
mv docs-early-access/data data/early-access
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/usr/bin/env bash
2+
3+
# [start-readme]
4+
#
5+
# This script removes files that are unnecessary for our preview environments.
6+
# This is typically run before a docker build to reduce the size of the build context sent to docker
7+
#
8+
# [end-readme]
9+
10+
# Remove all but the english search indexes
11+
find lib/search/indexes ! -name '*-en.json.br' ! -name '*-en-records.json.br' -maxdepth 1 -type f -delete
12+
13+
# Translations are never tested in preview environments
14+
# but let's keep the empty directory.
15+
rm -rf translations
16+
mkdir translations
17+
18+
# The assumption here is that a preview build will not
19+
# need these legacy redirects. Only the redirects from
20+
# front-matter will be at play.
21+
# These static redirects json files are notoriously large
22+
echo '[]' > lib/redirects/static/archived-frontmatter-fallbacks.json
23+
echo '{}' > lib/redirects/static/developer.json
24+
echo '{}' > lib/redirects/static/archived-redirects-from-213-to-217.json

0 commit comments

Comments
 (0)