1
0
mirror of synced 2025-12-21 19:06:49 -05:00

Merge branch 'main' into mm-cs-networking

This commit is contained in:
Mike McDonald
2021-12-07 15:15:59 -07:00
committed by GitHub
2586 changed files with 93134 additions and 78108 deletions

View File

@@ -21,7 +21,8 @@
"davidanson.vscode-markdownlint",
"bierner.markdown-preview-github-styles",
"yzhang.markdown-all-in-one",
"streetsidesoftware.code-spell-checker"
"streetsidesoftware.code-spell-checker",
"hubwriter.open-reusable"
],
// Use 'forwardPorts' to make a list of ports inside the container available locally.

2
.github/CODEOWNERS vendored
View File

@@ -16,9 +16,11 @@ package-lock.json @github/docs-engineering
package.json @github/docs-engineering
# Localization
/.github/workflows/create-translation-batch-pr.yml @github/docs-localization
/.github/workflows/crowdin.yml @github/docs-localization
/crowdin*.yml @github/docs-engineering @github/docs-localization
/translations/ @github/docs-engineering @github/docs-localization @github-actions
/translations/log/ @github/docs-localization
# Site Policy
/content/github/site-policy/ @github/site-policy-admins

View File

@@ -0,0 +1,63 @@
#!/usr/bin/env node
import path from 'path'
import fs from 'fs'
import zlib from 'zlib'
import walk from 'walk-sync'
const DRY_RUN = Boolean(JSON.parse(process.env.DRY_RUN || 'false'))
// Roughly 100KiB means about 25 files at the moment.
// Set this too low and the overheads will be more than the disk and
// network I/O that this intends to serve.
const MIN_GZIP_SIZE = Number(process.env.MIN_GZIP_SIZE || 1024 * 100)
const BROTLI_OPTIONS = {
params: {
[zlib.constants.BROTLI_PARAM_MODE]: zlib.constants.BROTLI_MODE_TEXT,
[zlib.constants.BROTLI_PARAM_QUALITY]: 6,
},
}
main()
async function main() {
compressFromPattern('lib/**/static/**/*.json')
}
async function compressFromPattern(pattern) {
const glob = pattern.includes('*') ? pattern.split(path.sep).slice(1).join(path.sep) : undefined
const walkOptions = {
globs: glob ? [glob] : undefined,
directories: false,
includeBasePath: true,
}
const root = path.resolve(pattern.includes('*') ? pattern.split(path.sep)[0] : pattern)
const filePaths = walk(root, walkOptions).filter((filePath) => {
return fs.statSync(filePath).size > MIN_GZIP_SIZE
})
if (!DRY_RUN) {
console.time(`Compress ${filePaths.length} files`)
const compressed = await Promise.all(filePaths.map(compressFile))
console.timeEnd(`Compress ${filePaths.length} files`)
console.time(`Delete ${compressed.length} files`)
compressed.forEach((filePath) => fs.unlinkSync(filePath))
console.timeEnd(`Delete ${compressed.length} files`)
}
}
function compressFile(filePath) {
return new Promise((resolve, reject) => {
const contentStream = fs.createReadStream(filePath)
const newFilePath = `${filePath}.br`
const writeStream = fs.createWriteStream(newFilePath)
const compressor = zlib.createBrotliCompress(BROTLI_OPTIONS)
contentStream
.pipe(compressor)
.pipe(writeStream)
.on('finish', (err) => {
if (err) return reject(err)
resolve(filePath)
})
})
}

View File

@@ -0,0 +1,54 @@
#!/usr/bin/env node
import createStagingAppName from '../../script/deployment/create-staging-app-name.js'
import * as github from '@actions/github'
import { setOutput } from '@actions/core'
const context = github.context
const githubToken = process.env.GITHUB_TOKEN
if (!githubToken) {
throw new Error(`GITHUB_TOKEN environment variable not set`)
}
const stagingPrefix = createStagingAppName({
repo: context.payload.repository.name,
pullNumber: context.payload.number,
branch: context.payload.pull_request.head.ref,
})
const octokit = github.getOctokit(githubToken)
const response = await octokit.rest.repos.compareCommits({
owner: context.repo.owner,
repo: context.payload.repository.name,
base: context.payload.pull_request.base.sha,
head: context.payload.pull_request.head.sha,
})
const { files } = response.data
let markdownTable =
'| **Source** | **Staging** | **Production** | **What Changed** |\n|:----------- |:----------- |:----------- |:----------- |\n'
const pathPrefix = 'content/'
const articleFiles = files.filter(
({ filename }) => filename.startsWith(pathPrefix) && !filename.endsWith('/index.md')
)
for (const file of articleFiles) {
const sourceUrl = file.blob_url
const fileName = file.filename.slice(pathPrefix.length)
const fileUrl = fileName.slice(0, fileName.lastIndexOf('.'))
const stagingLink = `https://${stagingPrefix}.herokuapp.com/${fileUrl}`
const productionLink = `https://docs.github.com/${fileUrl}`
let markdownLine = ''
if (file.status === 'modified') {
markdownLine = `| [content/${fileName}](${sourceUrl}) | [Modified](${stagingLink}) | [Original](${productionLink}) | |\n`
} else if (file.status === 'added') {
markdownLine = `| New file: [content/${fileName}](${sourceUrl}) | [Modified](${stagingLink}) | | |\n`
}
markdownTable += markdownLine
}
setOutput('changesTable', markdownTable)

View File

@@ -12,13 +12,13 @@ If you aren't comfortable going through the steps alone, sync up with a docs eng
- [ ] Increment the `next` variable above the `supported` array (e.g., new release number + `.1`).
- [ ] Increment the `nextNext` variable above the `supported` array (e.g., new release number + `.2`).
- [ ] Update the GHES dates file:
- [ ] Make sure you have a `.env` file at the root directory of your local checkout, and that it contains a PAT in the format of `GITHUB_TOKEN=<token>`.
- [ ] Make sure you have a `.env` file at the root directory of your local checkout, and that it contains a PAT in the format of `GITHUB_TOKEN=<token>` with `repo` scope. Ensure the PAT is SSO-enabled for the `github` org.
- [ ] Run the script to update the dates file:
```
script/update-enterprise-dates.js
```
- [ ] Create REST files based on previous version:
- [ ] Create REST files based on previous version. For example `script/enterprise-server-releases/create-rest-files.js --oldVersion enterprise-server@3.2 --newVersion enterprise-server@3.3`:
```
script/enterprise-server-releases/create-rest-files.js --oldVersion <PLAN@RELEASE> --newVersion <PLAN@RELEASE>
@@ -33,7 +33,7 @@ If you aren't comfortable going through the steps alone, sync up with a docs eng
```
script/enterprise-server-releases/create-webhook-files.js --oldVersion <PLAN@RELEASE> --newVersion <PLAN@RELEASE>
```
- [ ] Create a placeholder release notes file called `data/release-notes/<PRODUCT>/<RELEASE NUMBER>/PLACEHOLDER.yml`. For example `data/release-notes/3-1/PLACEHOLDER.yml`. Add the following placeholder content to the file:
- [ ] Create a placeholder release notes file called `data/release-notes/<PRODUCT>/<RELEASE NUMBER>/PLACEHOLDER.yml`. For example `data/release-notes/enterprise-server/3-1/PLACEHOLDER.yml`. Add the following placeholder content to the file:
```
date: '2021-05-04'
@@ -55,6 +55,8 @@ If you aren't comfortable going through the steps alone, sync up with a docs eng
script/enterprise-server-releases/release-banner.js --action create --version <PLAN@RELEASE>
```
- [ ] Create a PR with the above changes. This PR is used to track all docs changes and smoke tests associated with the release. For example https://github.com/github/docs-internal/pull/22286.
### When the `docs-internal` release branch is open
- [ ] Add a label to the PR in this format:
@@ -102,7 +104,7 @@ This file should be automatically updated, but you can also run `script/update-e
Usually, we should smoke test any new GHES admin guides, any large features landing in this GHES version for the first time, and the REST and GraphQL API references.
- [ ] Alert the Neon Squad (formally docs-ecosystem team) 1-2 days before the release to deploy to `github/github`. A PR should already be open in `github/github`, to change `published` to `true` in `app/api/description/config/releases/ghes-<NEXT RELEASE NUMBER>.yaml`. They will need to:
- [ ] Get the required approval from `@github/ecosystem-api-reviewers` then deploy the PR to dotcom. This process generally takes 30-90 minutes.
- [ ] Once the PR merges, make sure that the auto-generated PR titled "Update OpenAPI Descriptions" in doc-internal contains both the derefrenced and decorated JSON files for the new GHES release. If everything looks good, merge the "Update OpenAPI Description" PR into the GHES release megabranch.
- [ ] Once the PR merges, make sure that the auto-generated PR titled "Update OpenAPI Descriptions" in doc-internal contains both the derefrenced and decorated JSON files for the new GHES release. If everything looks good, merge the "Update OpenAPI Description" PR into the GHES release megabranch. **Note:** Be careful about resolving the conflicts correctly—you may wish to delete the existing OpenAPI files for the release version from the megabranch, so there are no conflicts to resolve and to ensure that the incoming artifacts are the correct ones.
- [ ] Add a blocking review to the auto-generated "Update OpenAPI Descriptions" PR in the public REST API description. (Remove this blocking review once the GHES release ships.)
- [ ] [Freeze the repos](https://github.com/github/docs-content/blob/main/docs-content-docs/docs-content-workflows/freezing.md) at least 1-2 days before the release, and post an announcement in Slack so everybody knows.
@@ -113,8 +115,9 @@ This file should be automatically updated, but you can also run `script/update-e
Use admin permissions to ship the release branch with this failure. Make sure that the merge's commit title does not include anything like `[DO NOT MERGE]`, and remove all the branch's commit details from the merge's commit message except for the co-author list.
- [ ] Do any required smoke tests listed in the opening post in the megabranch PR.
- [ ] Push the search index LFS objects for the public `github/docs` repo. The LFS objects were already being pushed for the internal repo after the `sync-english-index-for-<PLAN@RELEASE>` was added to the megabranch. To push the LFS objects, run the [search sync workflow](https://github.com/github/docs-internal/actions/workflows/sync-search-indices.yml) with the following inputs:
- [ ] Once smoke tests have passed, you can [unfreeze the repos](https://github.com/github/docs-content/blob/main/docs-content-docs/docs-content-workflows/freezing.md) and post an announcement in Slack.
- [ ] After unfreezing, push the search index LFS objects for the public `github/docs` repo. The LFS objects were already being pushed for the internal repo after the `sync-english-index-for-<PLAN@RELEASE>` was added to the megabranch. To push the LFS objects, run the [search sync workflow](https://github.com/github/docs-internal/actions/workflows/sync-search-indices.yml) with the following inputs:
version: `enterprise-server@<RELEASE>`
language: `en`
- [ ] Once smoke tests have passed, you can [unfreeze the repos](https://github.com/github/docs-content/blob/main/docs-content-docs/docs-content-workflows/freezing.md) and post an announcement in Slack.
- [ ] After unfreezing, if there were significant or highlighted GraphQL changes in the release, consider manually running the [GraphQL update workflow](https://github.com/github/docs-internal/actions/workflows/update-graphql-files.yml) to update our GraphQL schemas. By default this workflow only runs once every 24 hours.
- [ ] After the release, in the `docs-content` repo, add the now live version number to the "Specific GHES version(s)" section in the following files: [`.github/ISSUE_TEMPLATE/release-tier-1-or-2-tracking.yml`](https://github.com/github/docs-content/blob/main/.github/ISSUE_TEMPLATE/release-tier-1-or-2-tracking.yml) and [`.github/ISSUE_TEMPLATE/release-tier-3-or-tier-4.yml`](https://github.com/github/docs-content/blob/main/.github/ISSUE_TEMPLATE/release-tier-3-or-tier-4.yml). When the PR is approved, merge it in.

View File

@@ -120,7 +120,7 @@ async function run() {
const featureID = findFieldID('Feature', data)
const contributorTypeID = findFieldID('Contributor type', data)
const sizeTypeID = findFieldID('Size', data)
const authorID = findFieldID('Author', data)
const authorID = findFieldID('Contributor', data)
// Get the ID of the single select values that we want to set
const readyForReviewID = findSingleSelectID('Ready for review', 'Status', data)

51
.github/actions-scripts/prod-deploy.js vendored Executable file
View File

@@ -0,0 +1,51 @@
#!/usr/bin/env node
import getOctokit from '../../script/helpers/github.js'
import deployToProduction from '../../script/deployment/deploy-to-production.js'
const {
GITHUB_TOKEN,
HEROKU_API_TOKEN,
HEROKU_PRODUCTION_APP_NAME,
SOURCE_BLOB_URL,
DELAY_FOR_PREBOOT,
RUN_ID,
} = process.env
// Exit if GitHub Actions PAT is not found
if (!GITHUB_TOKEN) {
throw new Error('You must supply a GITHUB_TOKEN environment variable!')
}
// Exit if Heroku API token is not found
if (!HEROKU_API_TOKEN) {
throw new Error('You must supply a HEROKU_API_TOKEN environment variable!')
}
// Exit if Heroku App name is not found
if (!HEROKU_PRODUCTION_APP_NAME) {
throw new Error('You must supply a HEROKU_PRODUCTION_APP_NAME environment variable!')
}
if (!RUN_ID) {
throw new Error('$RUN_ID not set')
}
// This helper uses the `GITHUB_TOKEN` implicitly!
// We're using our usual version of Octokit vs. the provided `github`
// instance to avoid versioning discrepancies.
const octokit = getOctokit()
try {
await deployToProduction({
octokit,
includeDelayForPreboot: DELAY_FOR_PREBOOT !== 'false',
// These parameters will ONLY be set by Actions
sourceBlobUrl: SOURCE_BLOB_URL,
runId: RUN_ID,
})
} catch (error) {
console.error(`Failed to deploy to production: ${error.message}`)
console.error(error)
throw error
}

View File

@@ -0,0 +1,11 @@
#!/usr/bin/env node
import purgeEdgeCache from '../../script/deployment/purge-edge-cache.js'
try {
await purgeEdgeCache()
} catch (error) {
console.error(`Failed to purge the edge cache: ${error.message}`)
console.error(error)
throw error
}

View File

@@ -60,7 +60,7 @@ async function run() {
const featureID = findFieldID('Feature', data)
const contributorTypeID = findFieldID('Contributor type', data)
const sizeTypeID = findFieldID('Size', data)
const authorID = findFieldID('Author', data)
const authorID = findFieldID('Contributor', data)
// Get the ID of the single select values that we want to set
const readyForReviewID = findSingleSelectID('Ready for review', 'Status', data)

74
.github/actions-scripts/staging-deploy.js vendored Executable file
View File

@@ -0,0 +1,74 @@
#!/usr/bin/env node
import parsePrUrl from '../../script/deployment/parse-pr-url.js'
import getOctokit from '../../script/helpers/github.js'
import deployToStaging from '../../script/deployment/deploy-to-staging.js'
const { GITHUB_TOKEN, HEROKU_API_TOKEN } = process.env
// Exit if GitHub Actions PAT is not found
if (!GITHUB_TOKEN) {
throw new Error('You must supply a GITHUB_TOKEN environment variable!')
}
// Exit if Heroku API token is not found
if (!HEROKU_API_TOKEN) {
throw new Error('You must supply a HEROKU_API_TOKEN environment variable!')
}
// This helper uses the `GITHUB_TOKEN` implicitly!
// We're using our usual version of Octokit vs. the provided `github`
// instance to avoid versioning discrepancies.
const octokit = getOctokit()
const { RUN_ID, PR_URL, SOURCE_BLOB_URL, CONTEXT_NAME, ACTIONS_RUN_LOG, HEAD_SHA } = process.env
if (!RUN_ID) {
throw new Error('$RUN_ID not set')
}
if (!PR_URL) {
throw new Error('$PR_URL not set')
}
if (!SOURCE_BLOB_URL) {
throw new Error('$SOURCE_BLOB_URL not set')
}
if (!CONTEXT_NAME) {
throw new Error('$CONTEXT_NAME not set')
}
if (!ACTIONS_RUN_LOG) {
throw new Error('$ACTIONS_RUN_LOG not set')
}
if (!HEAD_SHA) {
throw new Error('$HEAD_SHA not set')
}
const { owner, repo, pullNumber } = parsePrUrl(PR_URL)
if (!owner || !repo || !pullNumber) {
throw new Error(
`'pullRequestUrl' input must match URL format 'https://github.com/github/(docs|docs-internal)/pull/123' but was '${PR_URL}'`
)
}
const { data: pullRequest } = await octokit.pulls.get({
owner,
repo,
pull_number: pullNumber,
})
await deployToStaging({
octokit,
pullRequest,
forceRebuild: false,
// These parameters will ONLY be set by Actions
sourceBlobUrl: SOURCE_BLOB_URL,
runId: RUN_ID,
})
await octokit.repos.createCommitStatus({
owner,
repo,
sha: HEAD_SHA,
context: CONTEXT_NAME,
state: 'success',
description: 'Successfully deployed! See logs.',
target_url: ACTIONS_RUN_LOG,
})

50
.github/actions-scripts/staging-undeploy.js vendored Executable file
View File

@@ -0,0 +1,50 @@
#!/usr/bin/env node
import parsePrUrl from '../../script/deployment/parse-pr-url.js'
import getOctokit from '../../script/helpers/github.js'
import undeployFromStaging from '../../script/deployment/undeploy-from-staging.js'
const { GITHUB_TOKEN, HEROKU_API_TOKEN } = process.env
// Exit if GitHub Actions PAT is not found
if (!GITHUB_TOKEN) {
throw new Error('You must supply a GITHUB_TOKEN environment variable!')
}
// Exit if Heroku API token is not found
if (!HEROKU_API_TOKEN) {
throw new Error('You must supply a HEROKU_API_TOKEN environment variable!')
}
// This helper uses the `GITHUB_TOKEN` implicitly!
// We're using our usual version of Octokit vs. the provided `github`
// instance to avoid versioning discrepancies.
const octokit = getOctokit()
const { RUN_ID, PR_URL } = process.env
if (!RUN_ID) {
throw new Error('$RUN_ID not set')
}
if (!PR_URL) {
throw new Error('$PR_URL not set')
}
const { owner, repo, pullNumber } = parsePrUrl(PR_URL)
if (!owner || !repo || !pullNumber) {
throw new Error(
`'pullRequestUrl' input must match URL format 'https://github.com/github/(docs|docs-internal)/pull/123' but was '${PR_URL}'`
)
}
const { data: pullRequest } = await octokit.pulls.get({
owner,
repo,
pull_number: pullNumber,
})
await undeployFromStaging({
octokit,
pullRequest: pullRequest,
runId: RUN_ID,
})

View File

@@ -5,10 +5,10 @@
export default [
'actions/cache@c64c572235d810460d0d6876e9c705ad5002b353', // v2.1.6
'actions/checkout@1e204e9a9253d643386038d443f96446fa156a97', // v2.3.5
'actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579', // v2.4.0
'actions/github-script@2b34a689ec86a68d8ab9478298f91d5401337b7d', // v4.0.2
'actions/labeler@5f867a63be70efff62b767459b009290364495eb', // v2.2.0
'actions/setup-node@270253e841af726300e85d718a5f606959b2903c', // v2.4.1
'actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458', // v2.5.0
'actions/stale@cdf15f641adb27a71842045a94023bef6945e3aa', // v4.0.0
'actions/upload-artifact@27121b0bdffd731efa15d66772be8dc71245d074', // v2.2.4
'alex-page/github-project-automation-plus@bb266ff4dde9242060e2d5418e120a133586d488', // v0.8.1

View File

@@ -23,5 +23,5 @@ jobs:
only-labels: 'engineering,Triaged,Improve existing docs,Core,Ecosystem'
stale-issue-label: 'stale'
stale-pr-label: 'stale'
exempt-pr-labels: 'never-stale'
exempt-pr-labels: 'never-stale,waiting for review'
exempt-issue-labels: 'never-stale,help wanted,waiting for review'

View File

@@ -31,10 +31,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repo content
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Setup Node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm

View File

@@ -10,6 +10,17 @@ on:
branches:
- main
pull_request:
paths:
- '**.js'
- '**.mjs'
- '**.ts'
- '**.tsx'
- jest.config.js
- package.json
# In case something like eslint or tsc or prettier upgrades
- package-lock.json
# Ultimately, for debugging this workflow itself
- .github/workflows/browser-test.yml
jobs:
build:
@@ -18,19 +29,24 @@ jobs:
# Each of these ifs needs to be repeated at each step to make sure the required check still runs
# Even if if doesn't do anything
- name: Checkout
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
with:
lfs: true
- name: Checkout LFS objects
run: git lfs checkout
- name: Setup Node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm
- name: Install dependencies
env:
# This makes it so the puppeteer npm package doesn't bother
# to download a copy of chromium because it can use
# `$PUPPETEER_EXECUTABLE_PATH` from the ubuntu Action container.
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: true
run: npm ci --include=optional
- name: Run browser-test

View File

@@ -30,6 +30,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Build the container
run: docker build --target production .

View File

@@ -22,9 +22,9 @@ jobs:
REPORT_REPOSITORY: github/docs-content
steps:
- name: Check out repo's default branch
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Setup Node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm

View File

@@ -36,10 +36,10 @@ jobs:
exit 1 # prevents further steps from running
- name: Checkout
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Setup Node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm

View File

@@ -20,7 +20,7 @@ jobs:
if: github.repository == 'github/docs-internal' || github.repository == 'github/docs'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
- uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- uses: github/codeql-action/init@v1
with:
languages: javascript # comma separated list of values from {go, python, javascript, java, cpp, csharp} (not YET ruby, sorry!)

View File

@@ -11,6 +11,7 @@ on:
jobs:
PR-Preview-Links:
if: github.event.pull_request.user.login != 'Octomerger'
name: Add staging/live links to PR
runs-on: ubuntu-latest
outputs:
@@ -38,10 +39,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: check out repo content
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Setup Node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm
@@ -49,57 +50,12 @@ jobs:
- name: Install temporary dependencies
run: |
npm install --no-save github-slugger
npm install --no-save --include=optional esm
- name: Get changes table
uses: actions/github-script@2b34a689ec86a68d8ab9478298f91d5401337b7d
id: changes
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
script: |
// Workaround to allow us to load ESM files with `require(...)`
const esm = require('esm')
require = esm({})
const { default: createStagingAppName } = require('./script/deployment/create-staging-app-name')
const stagingPrefix = createStagingAppName({
repo: context.payload.repository.name,
pullNumber: context.payload.number,
branch: context.payload.pull_request.head.ref,
})
const response = await github.repos.compareCommits({
owner: context.repo.owner,
repo: context.repo.repo,
base: context.payload.pull_request.base.sha,
head: context.payload.pull_request.head.sha
})
const files = response.data.files
let markdownTable = '| **Source** | **Staging** | **Production** | **What Changed** |\n|:----------- |:----------- |:----------- |:----------- |\n'
const pathPrefix = 'content/'
const articleFiles = files.filter(({ filename }) => filename.startsWith(pathPrefix) && !filename.endsWith('/index.md'))
for (const file of articleFiles) {
const sourceUrl = file.blob_url
const fileName = file.filename.slice(pathPrefix.length)
const fileUrl = fileName.slice(0, fileName.lastIndexOf('.'))
const stagingLink = `https://${stagingPrefix}.herokuapp.com/${fileUrl}`
const productionLink = `https://docs.github.com/${fileUrl}`
let markdownLine = ''
if (file.status === 'modified') {
markdownLine = `| [content/${fileName}](${sourceUrl}) | [Modified](${stagingLink}) | [Original](${productionLink}) | |\n`
} else if (file.status === 'added') {
markdownLine = `| New file: [content/${fileName}](${sourceUrl}) | [Modified](${stagingLink}) | | |\n`
}
markdownTable += markdownLine
}
core.setOutput('changesTable', markdownTable)
run: .github/actions-scripts/content-changes-table-comment.js
- name: Find content directory changes comment
uses: peter-evans/find-comment@d2dae40ed151c634e4189471272b57e76ec19ba8

View File

@@ -25,14 +25,22 @@ jobs:
max-parallel: 1
matrix:
include:
- language: pt-BR
language_code: pt
# - language: zh-CN
# language_code: cn
# - language: ja-JP
# language_code: ja
# - language: es-ES
# language_code: es
- language: pt
crowdin_language: pt-BR
language_dir: translations/pt-BR
- language: es
crowdin_language: es-ES
language_dir: translations/es-ES
- language: cn
crowdin_language: zh-CN
language_dir: translations/zh-CN
- language_dir: translations/ja-JP
crowdin_language: ja
language: ja
steps:
- name: Set branch name
id: set-branch
@@ -43,7 +51,7 @@ jobs:
- run: git config --global user.email "67483024+docubot@users.noreply.github.com"
- name: Checkout
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
with:
fetch-depth: 0
lfs: true
@@ -72,11 +80,11 @@ jobs:
- name: Remove all language translations
run: |
git rm -rf --quiet translations/${{ matrix.language }}/content
git rm -rf --quiet translations/${{ matrix.language }}/data
git rm -rf --quiet ${{ matrix.language_dir }}/content
git rm -rf --quiet ${{ matrix.language_dir }}/data
- name: Download crowdin translations
run: crowdin download --no-progress --no-colors --verbose --debug '--branch=main' '--config=crowdin.yml' --language=${{ matrix.language }}
run: crowdin download --no-progress --no-colors --verbose --debug '--branch=main' '--config=crowdin.yml' --language=${{ matrix.crowdin_language }}
env:
# This is a numeric id, not to be confused with Crowdin API v1 "project identifier" string
# See "API v2" on https://crowdin.com/project/<your-project>/settings#api
@@ -89,52 +97,59 @@ jobs:
- name: Commit crowdin sync
run: |
git add .
git add ${{ matrix.language_dir }}
git commit -m "Add crowdin translations" || echo "Nothing to commit"
- name: 'Setup node'
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: '16'
- run: npm ci
- name: Reset files with broken liquid tags
run: |
node script/i18n/reset-files-with-broken-liquid-tags.js --language=${{ matrix.language_code }}
git add . && git commit -m "run script/i18n/reset-files-with-broken-liquid-tags.js --language=${{ matrix.language_code }}" || echo "Nothing to commit"
# step 5 in docs-engineering/crowdin.md using script from docs-internal#22709
- name: Reset known broken files
run: |
node script/i18n/reset-known-broken-translation-files.js
git add . && git commit -m "run script/i18n/reset-known-broken-translation-files.js" || echo "Nothing to commit"
env:
GITHUB_TOKEN: ${{ secrets.DOCUBOT_REPO_PAT }}
# step 6 in docs-engineering/crowdin.md
- name: Homogenize frontmatter
run: |
node script/i18n/homogenize-frontmatter.js
git add . && git commit -m "Run script/i18n/homogenize-frontmatter.js" || echo "Nothing to commit"
git add ${{ matrix.language_dir }} && git commit -m "Run script/i18n/homogenize-frontmatter.js" || echo "Nothing to commit"
# step 7 in docs-engineering/crowdin.md
- name: Fix translation errors
run: |
node script/i18n/fix-translation-errors.js
git add . && git commit -m "Run script/i18n/fix-translation-errors.js" || echo "Nothing to commit"
git add ${{ matrix.language_dir }} && git commit -m "Run script/i18n/fix-translation-errors.js" || echo "Nothing to commit"
# step 8a in docs-engineering/crowdin.md
- name: Check parsing
run: |
node script/i18n/lint-translation-files.js --check parsing
git add . && git commit -m "Run script/i18n/lint-translation-files.js --check parsing" || echo "Nothing to commit"
node script/i18n/lint-translation-files.js --check parsing | tee -a /tmp/batch.log | cat
git add ${{ matrix.language_dir }} && git commit -m "Run script/i18n/lint-translation-files.js --check parsing" || echo "Nothing to commit"
# step 8b in docs-engineering/crowdin.md
- name: Check rendering
run: |
node script/i18n/lint-translation-files.js --check rendering
git add . && git commit -m "Run script/i18n/lint-translation-files.js --check rendering" || echo "Nothing to commit"
node script/i18n/lint-translation-files.js --check rendering | tee -a /tmp/batch.log | cat
git add ${{ matrix.language_dir }} && git commit -m "Run script/i18n/lint-translation-files.js --check rendering" || echo "Nothing to commit"
- name: Reset files with broken liquid tags
run: |
node script/i18n/reset-files-with-broken-liquid-tags.js --language=${{ matrix.language }} | tee -a /tmp/batch.log | cat
git add ${{ matrix.language_dir }} && git commit -m "run script/i18n/reset-files-with-broken-liquid-tags.js --language=${{ matrix.language }}" || echo "Nothing to commit"
# step 5 in docs-engineering/crowdin.md using script from docs-internal#22709
- name: Reset known broken files
run: |
node script/i18n/reset-known-broken-translation-files.js | tee -a /tmp/batch.log | cat
git add ${{ matrix.language_dir }} && git commit -m "run script/i18n/reset-known-broken-translation-files.js" || echo "Nothing to commit"
env:
GITHUB_TOKEN: ${{ secrets.DOCUBOT_REPO_PAT }}
- name: Check in CSV report
run: |
mkdir -p translations/log
csvFile=translations/log/${{ matrix.language }}-resets.csv
script/i18n/report-reset-files.js --report-type=csv --language=${{ matrix.language }} --log-file=/tmp/batch.log > $csvFile
git add -f $csvFile && git commit -m "Check in ${{ matrix.language }} CSV report" || echo "Nothing to commit"
- name: Create Pull Request
env:
@@ -142,11 +157,13 @@ jobs:
# We'll try to create the pull request based on the changes we pushed up in the branch.
# If there are actually no differences between the branch and `main`, we'll delete it.
run: |
script/i18n/report-reset-files.js --report-type=pull-request-body --language=${{ matrix.language }} --log-file=/tmp/batch.log > /tmp/pr-body.txt
git push origin ${{ steps.set-branch.outputs.BRANCH_NAME }}
gh pr create -t "New translation batch for ${{ matrix.language }}" \
gh pr create --title "New translation batch for ${{ matrix.language }}" \
--base=main \
--head=${{ steps.set-branch.outputs.BRANCH_NAME }} \
-b "New batch for ${{ matrix.language }} created by [this workflow]($GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID)" || git push origin :${{ steps.set-branch.outputs.BRANCH_NAME }}
--body-file /tmp/pr-body.txt || git push origin :${{ steps.set-branch.outputs.BRANCH_NAME }} \
--label "translation-batch"
# When the maximum execution time is reached for this job, Actions cancels the workflow run.
# This emits a notification for the first responder to triage.

View File

@@ -18,10 +18,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Setup Node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm

View File

@@ -19,7 +19,7 @@ jobs:
timeout-minutes: 300
steps:
- name: Checkout
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
with:
fetch-depth: 0
lfs: true

View File

@@ -20,10 +20,10 @@ jobs:
steps:
- name: Check out repo content
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Setup Node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm

View File

@@ -32,10 +32,10 @@ jobs:
exit 1 # prevents further steps from running
- name: Checkout repository code
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Setup Node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm

View File

@@ -36,13 +36,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
with:
ref: ${{ github.head_ref }}
token: ${{ secrets.DOCUBOT_REPO_PAT }}
- name: Setup Node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm

View File

@@ -40,7 +40,7 @@ jobs:
)
const logins = teamMembers.data.map(member => member.login)
// ignore PRs opened by docs bot accounts
logins.push('Octomerger', 'octoglot')
logins.push('Octomerger', 'octoglot', 'docubot')
if (logins.some(login => login === updatedIssueInformation.data.user.login)) {
console.log(`This issue or pull request was authored by a member of the github/docs team.`)
return 'true'

View File

@@ -25,10 +25,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Setup node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm

View File

@@ -18,10 +18,10 @@ jobs:
# Each of these ifs needs to be repeated at each step to make sure the required check still runs
# Even if if doesn't do anything
- name: Checkout
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Setup node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm

View File

@@ -18,10 +18,10 @@ jobs:
# Each of these ifs needs to be repeated at each step to make sure the required check still runs
# Even if if doesn't do anything
- name: Checkout
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Setup node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm

View File

@@ -16,10 +16,10 @@ jobs:
runs-on: ${{ fromJSON('["ubuntu-latest", "self-hosted"]')[github.repository == 'github/docs-internal'] }}
steps:
- name: Checkout
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Setup node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm

View File

@@ -18,10 +18,10 @@ jobs:
# Each of these ifs needs to be repeated at each step to make sure the required check still runs
# Even if if doesn't do anything
- name: Checkout
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Setup node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm

View File

@@ -16,10 +16,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository code
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Setup Node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm

View File

@@ -26,10 +26,10 @@ jobs:
add-labels: 'github-openapi-bot'
- name: Checkout repository code
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Setup node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm

View File

@@ -29,10 +29,10 @@ jobs:
runs-on: ${{ fromJSON('["ubuntu-latest", "self-hosted"]')[github.repository == 'github/docs-internal'] }}
steps:
- name: Checkout repository code
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Setup node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm

View File

@@ -44,10 +44,10 @@ jobs:
exit 1
- name: Check out repo content
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Setup Node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.x
cache: npm

View File

@@ -14,10 +14,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Setup Node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm

View File

@@ -19,10 +19,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Setup Node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.x

View File

@@ -16,9 +16,9 @@ jobs:
env:
HEROKU_API_TOKEN: ${{ secrets.HEROKU_API_TOKEN }}
steps:
- uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
- uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Setup node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm

View File

@@ -25,7 +25,7 @@ jobs:
timeout-minutes: 15
steps:
- name: Check out repo
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
with:
persist-credentials: 'false'
lfs: 'true'
@@ -34,7 +34,7 @@ jobs:
run: git lfs checkout
- name: Setup node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm
@@ -129,12 +129,8 @@ jobs:
-H 'Content-Type:' \
--data-binary @app.tar.gz
- name: Install one-off development-only dependencies
run: npm install --no-save --include=optional esm
- name: Deploy
id: deploy
uses: actions/github-script@2b34a689ec86a68d8ab9478298f91d5401337b7d
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HEROKU_API_TOKEN: ${{ secrets.HEROKU_API_TOKEN }}
@@ -144,56 +140,8 @@ jobs:
SOURCE_BLOB_URL: ${{ steps.build-source.outputs.download_url }}
DELAY_FOR_PREBOOT: 'true'
ALLOWED_POLLING_FAILURES_PER_PHASE: '15'
with:
script: |
const {
GITHUB_TOKEN,
HEROKU_API_TOKEN,
HEROKU_PRODUCTION_APP_NAME,
SOURCE_BLOB_URL,
DELAY_FOR_PREBOOT
} = process.env
// Exit if GitHub Actions PAT is not found
if (!GITHUB_TOKEN) {
throw new Error('You must supply a GITHUB_TOKEN environment variable!')
}
// Exit if Heroku API token is not found
if (!HEROKU_API_TOKEN) {
throw new Error('You must supply a HEROKU_API_TOKEN environment variable!')
}
// Exit if Heroku App name is not found
if (!HEROKU_PRODUCTION_APP_NAME) {
throw new Error('You must supply a HEROKU_PRODUCTION_APP_NAME environment variable!')
}
// Workaround to allow us to load ESM files with `require(...)`
const esm = require('esm')
require = esm({})
const { default: getOctokit } = require('./script/helpers/github')
const { default: deployToProduction } = require('./script/deployment/deploy-to-production')
// This helper uses the `GITHUB_TOKEN` implicitly!
// We're using our usual version of Octokit vs. the provided `github`
// instance to avoid versioning discrepancies.
const octokit = getOctokit()
try {
await deployToProduction({
octokit,
includeDelayForPreboot: DELAY_FOR_PREBOOT !== 'false',
// These parameters will ONLY be set by Actions
sourceBlobUrl: SOURCE_BLOB_URL,
runId: context.runId
})
} catch (error) {
console.error(`Failed to deploy to production: ${error.message}`)
console.error(error)
throw error
}
RUN_ID: ${{ github.run_id }}
run: .github/actions-scripts/prod-deploy.js
- name: Mark the deployment as inactive if timed out
uses: actions/github-script@2b34a689ec86a68d8ab9478298f91d5401337b7d
@@ -227,26 +175,11 @@ jobs:
console.log('⏲️ Deployment status: error - The deployment timed out...')
- name: Purge Fastly edge cache
uses: actions/github-script@2b34a689ec86a68d8ab9478298f91d5401337b7d
env:
FASTLY_TOKEN: ${{ secrets.FASTLY_TOKEN }}
FASTLY_SERVICE_ID: ${{ secrets.FASTLY_SERVICE_ID }}
FASTLY_SURROGATE_KEY: 'all-the-things'
with:
script: |
// Workaround to allow us to load ESM files with `require(...)`
const esm = require('esm')
require = esm({})
const { default: purgeEdgeCache } = require('./script/deployment/purge-edge-cache')
try {
await purgeEdgeCache()
} catch (error) {
console.error(`Failed to purge the edge cache: ${error.message}`)
console.error(error)
throw error
}
run: .github/actions-scripts/purge-fastly-edge-cache.js
- name: Send Slack notification if workflow failed
uses: someimportantcompany/github-actions-slack-message@f8d28715e7b8a4717047d23f48c39827cacad340

View File

@@ -15,10 +15,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repo content
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Setup Node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm

View File

@@ -24,10 +24,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repo's default branch
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Setup Node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm
@@ -46,10 +46,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repo's default branch
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Setup Node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm

View File

@@ -22,9 +22,9 @@ jobs:
echo 'The repo is currently frozen! Exiting this workflow.'
exit 1 # prevents further steps from running
- name: Checkout
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Setup Node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm

View File

@@ -94,11 +94,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
# Set up npm and run npm ci to run husky to get githooks for LFS
- name: Setup node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm
@@ -128,6 +128,9 @@ jobs:
pr_body: "This is an automated pull request to sync changes between the public and private repos.\n\n:robot: This pull request should be merged (not squashed) to preserve continuity across repos, so please let a bot do the merging!"
pr_label: automated-reposync-pr
github_token: ${{ secrets.OCTOMERGER_PAT_WITH_REPO_AND_WORKFLOW_SCOPE }}
# This will exit 0 if there's no difference between `repo-sync`
# and `main`. And if so, no PR will be created.
pr_allow_empty: false
- name: Find pull request
uses: juliangruber/find-pull-request-action@db875662766249c049b2dcd85293892d61cb0b51

View File

@@ -26,10 +26,10 @@ jobs:
pull-requests: write
steps:
- name: checkout docs-internal
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: checkout public site-policy
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
with:
repository: github/site-policy
token: ${{ secrets.API_TOKEN_SITEPOLICY }}
@@ -37,6 +37,8 @@ jobs:
path: public-repo
- name: Commits internal policies to copy of public repo with descriptive message from triggering PR title
env:
PR_TITLE: ${{ github.event.pull_request.title }}
run: |
cd public-repo
git config --local user.name 'site-policy-bot'
@@ -46,7 +48,6 @@ jobs:
git status
git checkout -b automated-sync-$GITHUB_RUN_ID
git add .
PR_TITLE=${{ github.event.pull_request.title }}
echo PR_TITLE: $PR_TITLE
[[ ! -z $PR_TITLE ]] && DESCRIPTION="${PR_TITLE}" || DESCRIPTION="Update manually triggered by workflow"
echo "DESCRIPTION=$DESCRIPTION" >> $GITHUB_ENV

View File

@@ -30,15 +30,6 @@ concurrency:
cancel-in-progress: true
jobs:
debug:
runs-on: ubuntu-latest
steps:
- name: Dump full context for debugging
run: |
cat << EOF
${{ toJSON(github) }}
EOF
build-pr:
if: ${{ github.repository == 'github/docs-internal' || github.repository == 'github/docs' }}
runs-on: ${{ fromJSON('["ubuntu-latest", "self-hosted"]')[github.repository == 'github/docs-internal'] }}
@@ -50,7 +41,7 @@ jobs:
cancel-in-progress: true
steps:
- name: Check out repo
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
# Make sure only approved files are changed if it's in github/docs
- name: Check changed files
@@ -86,7 +77,7 @@ jobs:
run: exit 1
- name: Setup node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm
@@ -117,11 +108,43 @@ jobs:
run: npm set-script heroku-postbuild "echo 'Application was pre-built!'"
- name: Delete heavy things we won't need deployed
if: ${{ github.repository == 'github/docs-internal' }}
run: |
# The dereferenced file is not used in runtime once the
# decorated file has been created from it.
rm -fr lib/rest/static/dereferenced
# Translations are never tested in Staging builds
# but let's keep the empty directory.
rm -fr translations
mkdir translations
# Delete all the big search indexes that are NOT English (`*-en-*`)
pushd lib/search/indexes
ls | grep -v '\-en\-' | xargs rm
popd
# Note! Some day it would be nice to be able to delete
# all the heavy assets because they bloat the tarball.
# But it's not obvious how to test it then. For now, we'll have
# to accept that every staging build has a copy of the images.
# The assumption here is that a staging build will not
# need these legacy redirects. Only the redirects from
# front-matter will be at play.
# These static redirects json files are notoriously large
# and they make the tarball unnecessarily large.
echo '[]' > lib/redirects/static/archived-frontmatter-fallbacks.json
echo '{}' > lib/redirects/static/developer.json
echo '{}' > lib/redirects/static/archived-redirects-from-213-to-217.json
# This will turn every `lib/**/static/*.json` into
# an equivalent `lib/**/static/*.json.br` file.
# Once the server starts, it'll know to fall back to reading
# the `.br` equivalent if the `.json` file isn't present.
node .github/actions-scripts/compress-large-files.js
- name: Create an archive
# Only bother if this is actually a pull request
if: ${{ github.event.pull_request.number }}

View File

@@ -67,6 +67,10 @@ jobs:
BUILD_ACTIONS_RUN_ID: ${{ env.BUILD_ACTIONS_RUN_ID }}
with:
script: |
// Curious about what version of node you get
console.log('Node version:', process.version)
// In order to find out the PR info for a forked repo, we must query
// the API for more info based on the originating workflow run
const { BUILD_ACTIONS_RUN_ID } = process.env
@@ -289,7 +293,7 @@ jobs:
})
- name: Check out repo's default branch
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
with:
# To prevent issues with cloning early access content later
persist-credentials: 'false'
@@ -299,7 +303,7 @@ jobs:
run: git lfs checkout
- name: Setup node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm
@@ -471,10 +475,10 @@ jobs:
cancel-in-progress: true
steps:
- name: Check out repo's default branch
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Setup node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm
@@ -482,12 +486,8 @@ jobs:
- name: Install dependencies
run: npm ci
- name: Install one-off development-only dependencies
run: npm install --no-save --include=optional esm
- name: Deploy
id: deploy
uses: actions/github-script@2b34a689ec86a68d8ab9478298f91d5401337b7d
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HEROKU_API_TOKEN: ${{ secrets.HEROKU_API_TOKEN }}
@@ -499,69 +499,8 @@ jobs:
ACTIONS_RUN_LOG: ${{ env.ACTIONS_RUN_LOG }}
HEAD_SHA: ${{ needs.pr-metadata.outputs.head_sha }}
ALLOWED_POLLING_FAILURES_PER_PHASE: '15'
with:
script: |
const { GITHUB_TOKEN, HEROKU_API_TOKEN } = process.env
// Exit if GitHub Actions PAT is not found
if (!GITHUB_TOKEN) {
throw new Error('You must supply a GITHUB_TOKEN environment variable!')
}
// Exit if Heroku API token is not found
if (!HEROKU_API_TOKEN) {
throw new Error('You must supply a HEROKU_API_TOKEN environment variable!')
}
// Workaround to allow us to load ESM files with `require(...)`
const esm = require('esm')
require = esm({})
const { default: parsePrUrl } = require('./script/deployment/parse-pr-url')
const { default: getOctokit } = require('./script/helpers/github')
const { default: deployToStaging } = require('./script/deployment/deploy-to-staging')
// This helper uses the `GITHUB_TOKEN` implicitly!
// We're using our usual version of Octokit vs. the provided `github`
// instance to avoid versioning discrepancies.
const octokit = getOctokit()
try {
const { PR_URL, SOURCE_BLOB_URL, CONTEXT_NAME, ACTIONS_RUN_LOG, HEAD_SHA } = process.env
const { owner, repo, pullNumber } = parsePrUrl(PR_URL)
if (!owner || !repo || !pullNumber) {
throw new Error(`'pullRequestUrl' input must match URL format 'https://github.com/github/(docs|docs-internal)/pull/123' but was '${PR_URL}'`)
}
const { data: pullRequest } = await octokit.pulls.get({
owner,
repo,
pull_number: pullNumber
})
await deployToStaging({
octokit,
pullRequest,
forceRebuild: false,
// These parameters will ONLY be set by Actions
sourceBlobUrl: SOURCE_BLOB_URL,
runId: context.runId
})
await github.repos.createCommitStatus({
owner,
repo,
sha: HEAD_SHA,
context: CONTEXT_NAME,
state: 'success',
description: 'Successfully deployed! See logs.',
target_url: ACTIONS_RUN_LOG
})
} catch (error) {
console.error(`Failed to deploy to staging: ${error.message}`)
console.error(error)
throw error
}
RUN_ID: ${{ github.run_id }}
run: .github/actions-scripts/staging-deploy.js
- name: Mark the deployment as inactive if timed out
uses: actions/github-script@2b34a689ec86a68d8ab9478298f91d5401337b7d

View File

@@ -55,13 +55,13 @@ jobs:
add-labels: 'automated-block-deploy'
- name: Check out repo's default branch
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
with:
# For enhanced security: https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
persist-credentials: 'false'
- name: Setup node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm
@@ -69,51 +69,13 @@ jobs:
- name: Install dependencies
run: npm ci
- name: Install one-off development-only dependencies
run: npm install --no-save --include=optional esm
- name: Undeploy
uses: actions/github-script@2b34a689ec86a68d8ab9478298f91d5401337b7d
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HEROKU_API_TOKEN: ${{ secrets.HEROKU_API_TOKEN }}
with:
script: |
const { GITHUB_TOKEN, HEROKU_API_TOKEN } = process.env
// Exit if GitHub Actions PAT is not found
if (!GITHUB_TOKEN) {
throw new Error('You must supply a GITHUB_TOKEN environment variable!')
}
// Exit if Heroku API token is not found
if (!HEROKU_API_TOKEN) {
throw new Error('You must supply a HEROKU_API_TOKEN environment variable!')
}
// Workaround to allow us to load ESM files with `require(...)`
const esm = require('esm')
require = esm({})
const { default: getOctokit } = require('./script/helpers/github')
const { default: undeployFromStaging } = require('./script/deployment/undeploy-from-staging')
// This helper uses the `GITHUB_TOKEN` implicitly!
// We're using our usual version of Octokit vs. the provided `github`
// instance to avoid versioning discrepancies.
const octokit = getOctokit()
try {
await undeployFromStaging({
octokit,
pullRequest: context.payload.pull_request,
runId: context.runId
})
} catch (error) {
console.error(`Failed to undeploy from staging: ${error.message}`)
console.error(error)
throw error
}
RUN_ID: ${{ github.run_id }}
PR_URL: ${{ github.event.pull_request.html_url }}
run: .github/actions-scripts/staging-undeploy.js
- if: ${{ always() }}
name: Remove the label from the PR to unblock deployment

View File

@@ -48,12 +48,12 @@ jobs:
exit 1 # prevents further steps from running
# Check out internal docs repository
- name: checkout
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
with:
token: ${{ secrets.DOCS_BOT_FR }}
- name: Setup Node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm

40
.github/workflows/sync-search-pr.yml vendored Normal file
View File

@@ -0,0 +1,40 @@
name: Sync search - PR
# **What it does**: Tries running the sync-search when relevant files change.
# **Why we have it**: To test that the script works and the popular pages json is valid.
# **Who does it impact**: Docs engineering.
on:
pull_request:
paths:
- script/search/parse-page-sections-into-records.js
- script/search/popular-pages.js
- lib/search/popular-pages.json
# Ultimately, for debugging this workflow itself
- .github/workflows/sync-search-pr.yml
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Setup node
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Run sync-search
env:
# Set filtered to only these so it doesn't run for too long.
LANGUAGE: en
VERSION: free-pro-team@latest
run: npm run sync-search

View File

@@ -36,13 +36,13 @@ jobs:
]
steps:
- name: Check out repo
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
with:
# Enables cloning the Early Access repo later with the relevant PAT
persist-credentials: 'false'
- name: Setup node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm

View File

@@ -41,7 +41,7 @@ jobs:
# Each of these ifs needs to be repeated at each step to make sure the required check still runs
# Even if if doesn't do anything
- name: Check out repo
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
with:
# Enables cloning the Early Access repo later with the relevant PAT
persist-credentials: 'false'
@@ -56,10 +56,13 @@ jobs:
- name: Insight into changed files
run: |
echo ${{ steps.get_diff_files.outputs.files }}
# Must to do this because the list of files can be HUGE. Especially
# in a repo-sync when there are lots of translation files involved.
echo "${{ steps.get_diff_files.outputs.files }}" > get_diff_files.txt
- name: Setup node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm
@@ -67,18 +70,23 @@ jobs:
- name: Install dependencies
run: npm ci
- if: ${{ github.repository == 'github/docs-internal' }}
name: Clone early access
run: npm run heroku-postbuild
- name: Clone early access
if: ${{ github.repository == 'github/docs-internal' }}
run: script/early-access/clone-for-build.js
env:
DOCUBOT_REPO_PAT: ${{ secrets.DOCUBOT_REPO_PAT }}
GIT_BRANCH: ${{ github.head_ref || github.ref }}
- if: ${{ github.repository != 'github/docs-internal' }}
name: Run build script
- name: Cache nextjs build
uses: actions/cache@c64c572235d810460d0d6876e9c705ad5002b353
with:
path: .next/cache
key: ${{ runner.os }}-nextjs-${{ hashFiles('package*.json') }}-${{ hashFiles('.github/workflows/test.yml') }}
- name: Run build script
run: npm run build
- name: Run tests
env:
DIFF_FILES: ${{ steps.get_diff_files.outputs.files }}
DIFF_FILE: get_diff_files.txt
run: npm run test tests/${{ matrix.test-group }}/

View File

@@ -8,6 +8,10 @@ on:
schedule:
- cron: '45 16 * * *' # Run each day at 16:45 UTC / 8:45 PST
permissions:
issues: write
pull-requests: write
jobs:
stale_contributor:
if: github.repository == 'github/docs'
@@ -17,11 +21,15 @@ jobs:
- uses: actions/stale@cdf15f641adb27a71842045a94023bef6945e3aa
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'A stale label has been added to this issue becuase it has been open for 60 days with no activity. To keep this issue open, add a comment within 3 days.'
days-before-issue-stale: 60
days-before-issue-close: 3
exempt-issue-labels: 'help wanted,waiting for review'
stale-pr-message: 'A stale label has been added to this pull request because it has been open 7 days with no activity. To keep this PR open, add a comment or push a commit within 3 days.'
days-before-pr-stale: 7
days-before-pr-close: 3
stale-pr-label: 'stale'
exempt-pr-labels: 'waiting for review,never-stale, ready to merge'
exempt-pr-labels: 'waiting for review,never-stale,ready to merge'
stale_staff:
if: github.repository == 'github/docs'
runs-on: ubuntu-latest

View File

@@ -54,13 +54,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
with:
ref: ${{ github.head_ref }}
token: ${{ secrets.DOCUBOT_REPO_PAT }}
- name: Setup Node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm

View File

@@ -28,9 +28,9 @@ jobs:
echo 'The repo is currently frozen! Exiting this workflow.'
exit 1 # prevents further steps from running
- name: Checkout
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Setup Node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
with:
node-version: 16.13.x
cache: npm

View File

@@ -23,7 +23,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
- name: Run linter
uses: cschleiden/actions-linter@caffd707beda4fc6083926a3dff48444bc7c24aa

View File

@@ -1,37 +0,0 @@
name: Lint Yaml
# **What it does**: This lints our yaml files in the docs repository.
# **Why we have it**: We want some level of consistent formatting for YAML files.
# **Who does it impact**: Docs engineering, docs content.
on:
workflow_dispatch:
push:
branches:
- main
paths:
- '**/*.yml'
- '**/*.yaml'
pull_request:
paths:
- '**/*.yml'
- '**/*.yaml'
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
- name: Setup node
uses: actions/setup-node@270253e841af726300e85d718a5f606959b2903c
with:
node-version: 16.13.x
cache: npm
- name: Install dependencies
run: npm ci
- name: Run linter
run: npx prettier -c "**/*.{yml,yaml}"

1
.gitignore vendored
View File

@@ -10,6 +10,7 @@ coverage/
/data/early-access
.next
.eslintcache
*.tsbuildinfo
# blc: broken link checker
blc_output.log

BIN
.vscode/open-reusable-1.3.0.vsix vendored Normal file

Binary file not shown.

View File

@@ -2,4 +2,6 @@
"files.exclude": {
"**/translations": true
}
"workbench.editor.enablePreview": false,
"workbench.editor.enablePreviewFromQuickOpen": false
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 207 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -1,14 +1,12 @@
/* TODO remove mark styling if https://github.com/primer/css/pull/1756 ships */
.resultsContainer mark {
font-weight: bolder;
background: none;
color: inherit;
}
.searchResultContent mark {
color: var(--color-fg-default);
background-color: var(--color-attention-subtle);
font-weight: bolder;
}
/* end TODO */
.searchResultContent {
max-height: 4rem;

View File

@@ -436,7 +436,7 @@ function ShowSearchResults({
onClickOutside={() => closeSearch()}
aria-labelledby="title"
sx={
isHeaderSearch && {
(isHeaderSearch && {
background: 'none',
boxShadow: 'none',
position: 'static',
@@ -445,7 +445,8 @@ function ShowSearchResults({
maxWidth: '96%',
margin: '1.5em 2em 0 0.5em',
scrollbarWidth: 'none',
}
}) ||
{}
}
>
{ActionListResults}

View File

@@ -15,6 +15,7 @@ import { MarkdownContent } from 'components/ui/MarkdownContent'
import { Lead } from 'components/ui/Lead'
import { ArticleGridLayout } from './ArticleGridLayout'
import { PlatformPicker } from 'components/article/PlatformPicker'
import { ToolPicker } from 'components/article/ToolPicker'
// Mapping of a "normal" article to it's interactive counterpart
const interactiveAlternatives: Record<string, { href: string }> = {
@@ -24,6 +25,22 @@ const interactiveAlternatives: Record<string, { href: string }> = {
'/actions/automating-builds-and-tests/building-and-testing-python': {
href: '/actions/automating-builds-and-tests/building-and-testing-nodejs-or-python?langId=python',
},
'/codespaces/setting-up-your-project-for-codespaces/setting-up-your-nodejs-project-for-codespaces':
{
href: '/codespaces/setting-up-your-project-for-codespaces/setting-up-your-project-for-codespaces?langId=nodejs',
},
'/codespaces/setting-up-your-project-for-codespaces/setting-up-your-dotnet-project-for-codespaces':
{
href: '/codespaces/setting-up-your-project-for-codespaces/setting-up-your-project-for-codespaces?langId=dotnet',
},
'/codespaces/setting-up-your-project-for-codespaces/setting-up-your-java-project-for-codespaces':
{
href: '/codespaces/setting-up-your-project-for-codespaces/setting-up-your-project-for-codespaces?langId=java',
},
'/codespaces/setting-up-your-project-for-codespaces/setting-up-your-python-project-for-codespaces':
{
href: '/codespaces/setting-up-your-project-for-codespaces/setting-up-your-project-for-codespaces?langId=py',
},
}
export const ArticlePage = () => {
@@ -36,6 +53,7 @@ export const ArticlePage = () => {
contributor,
permissions,
includesPlatformSpecificContent,
includesToolSpecificContent,
product,
miniTocItems,
currentLearningTrack,
@@ -51,7 +69,7 @@ export const ArticlePage = () => {
className={item.platform}
sx={{ listStyle: 'none', padding: '2px' }}
>
<div className={cx('lh-condensed')}>
<div className={cx('lh-condensed d-block width-full')}>
<div dangerouslySetInnerHTML={{ __html: item.contents }} />
{item.items && item.items.length > 0 ? (
<ul className="ml-3">{item.items.map(renderTocItem)}</ul>
@@ -95,6 +113,7 @@ export const ArticlePage = () => {
)}
{includesPlatformSpecificContent && <PlatformPicker variant="underlinenav" />}
{includesToolSpecificContent && <ToolPicker variant="underlinenav" />}
{product && (
<Callout

View File

@@ -12,9 +12,11 @@ const platforms = [
{ id: 'linux', label: 'Linux' },
]
// Nota bene: platform === os
// Imperatively modify article content to show only the selected platform
// find all platform-specific *block* elements and hide or show as appropriate
// example: {% mac } block content {% mac %}
// example: {% mac %} block content {% endmac %}
function showPlatformSpecificContent(platform: string) {
const markdowns = Array.from(document.querySelectorAll<HTMLElement>('.extended-markdown'))
markdowns

View File

@@ -0,0 +1,121 @@
import { useEffect, useState } from 'react'
import Cookies from 'js-cookie'
import { UnderlineNav } from '@primer/components'
import { sendEvent, EventType } from 'components/lib/events'
import { preserveAnchorNodePosition } from 'scroll-anchoring'
import { useArticleContext } from 'components/context/ArticleContext'
// example: http://localhost:4000/en/codespaces/developing-in-codespaces/creating-a-codespace
// Nota bene: tool === application
// Nota bene: picker === switcher
const supportedTools = ['cli', 'desktop', 'webui', 'curl', 'codespaces', 'vscode']
const toolTitles = {
webui: 'Web browser',
cli: 'GitHub CLI',
curl: 'cURL',
desktop: 'Desktop',
codespaces: 'Codespaces',
vscode: 'Visual Studio Code',
} as Record<string, string>
// Imperatively modify article content to show only the selected tool
// find all platform-specific *block* elements and hide or show as appropriate
// example: {% webui %} block content {% endwebui %}
function showToolSpecificContent(tool: string) {
const markdowns = Array.from(document.querySelectorAll<HTMLElement>('.extended-markdown'))
markdowns
.filter((el) => supportedTools.some((tool) => el.classList.contains(tool)))
.forEach((el) => {
el.style.display = el.classList.contains(tool) ? '' : 'none'
})
// find all tool-specific *inline* elements and hide or show as appropriate
// example: <span class="tool-webui">inline content</span>
const toolEls = Array.from(
document.querySelectorAll<HTMLElement>(supportedTools.map((tool) => `.tool-${tool}`).join(', '))
)
toolEls.forEach((el) => {
el.style.display = el.classList.contains(`tool-${tool}`) ? '' : 'none'
})
}
function getDefaultTool(defaultTool: string | undefined, detectedTools: Array<string>): string {
// If there is a default tool and the tool is present on this page
if (defaultTool && detectedTools.includes(defaultTool)) return defaultTool
// Default to webui if present (this is generally the case where we show UI/CLI/Desktop info)
if (detectedTools.includes('webui')) return 'webui'
// Default to cli if present (this is generally the case where we show curl/CLI info)
if (detectedTools.includes('cli')) return 'cli'
// Otherwise, just choose the first detected tool
return detectedTools[0]
}
type Props = {
variant?: 'subnav' | 'tabnav' | 'underlinenav'
}
export const ToolPicker = ({ variant = 'subnav' }: Props) => {
const { defaultTool, detectedTools } = useArticleContext()
const [currentTool, setCurrentTool] = useState(getDefaultTool(defaultTool, detectedTools))
const sharedContainerProps = {
'data-testid': 'tool-picker',
'aria-label': 'Tool picker',
'data-default-tool': defaultTool,
className: 'mb-4',
}
// Run on mount for client-side only features
useEffect(() => {
// If the user selected a tool preference and the tool is present on this page
// Has to be client-side only for cookie reading
const cookieValue = Cookies.get('toolPreferred')
if (cookieValue && detectedTools.includes(cookieValue)) {
setCurrentTool(cookieValue)
}
}, [])
// Whenever the currentTool is changed, update the article content
useEffect(() => {
preserveAnchorNodePosition(document, () => {
showToolSpecificContent(currentTool)
})
}, [currentTool])
function onClickTool(tool: string) {
setCurrentTool(tool)
sendEvent({
type: EventType.preference,
preference_name: 'application',
preference_value: tool,
})
Cookies.set('toolPreferred', tool, { sameSite: 'strict', secure: true })
}
if (variant === 'underlinenav') {
return (
<UnderlineNav {...sharedContainerProps}>
{detectedTools.map((tool) => (
<UnderlineNav.Link
key={tool}
data-tool={tool}
as="button"
selected={tool === currentTool}
onClick={() => {
onClickTool(tool)
}}
>
{toolTitles[tool]}
</UnderlineNav.Link>
))}
</UnderlineNav>
)
}
return null
}

View File

@@ -22,10 +22,13 @@ export type ArticleContextT = {
contributor: { name: string; URL: string } | null
permissions?: string
includesPlatformSpecificContent: boolean
includesToolSpecificContent: boolean
defaultPlatform?: string
defaultTool?: string
product?: string
currentLearningTrack?: LearningTrack
detectedPlatforms: Array<string>
detectedTools: Array<string>
}
export const ArticleContext = createContext<ArticleContextT | null>(null)
@@ -60,9 +63,12 @@ export const getArticleContextFromRequest = (req: any): ArticleContextT => {
contributor: page.contributor || null,
permissions: page.permissions || '',
includesPlatformSpecificContent: page.includesPlatformSpecificContent || false,
includesToolSpecificContent: page.includesToolSpecificContent || false,
defaultPlatform: page.defaultPlatform || '',
defaultTool: page.defaultTool || '',
product: page.product || '',
currentLearningTrack: req.context.currentLearningTrack,
detectedPlatforms: page.detectedPlatforms || [],
detectedTools: page.detectedTools || [],
}
}

View File

@@ -2,14 +2,21 @@ import React, { createContext, useContext, useState } from 'react'
import { CodeLanguage, PlaygroundArticleT } from 'components/playground/types'
import { useRouter } from 'next/router'
import jsArticle from 'components/playground/content/building-and-testing/nodejs'
import pyArticle from 'components/playground/content/building-and-testing/python'
import actionsJsArticle from 'components/playground/content/actions/guides/building-and-testing-nodejs-or-python/nodejs'
import actionsPyArticle from 'components/playground/content/actions/guides/building-and-testing-nodejs-or-python/python'
import codespacesJsArticle from 'components/playground/content/codespaces/setting-up-your-project-for-codespaces/setting-up-your-project-for-codespaces/nodejs'
import codespacesPyArticle from 'components/playground/content/codespaces/setting-up-your-project-for-codespaces/setting-up-your-project-for-codespaces/python'
import codespacesNetArticle from 'components/playground/content/codespaces/setting-up-your-project-for-codespaces/setting-up-your-project-for-codespaces/dotnet'
import codespacesJavaArticle from 'components/playground/content/codespaces/setting-up-your-project-for-codespaces/setting-up-your-project-for-codespaces/java'
const articles = [jsArticle, pyArticle]
const articlesByLangId = articles.reduce((obj, item) => {
obj[item.codeLanguageId] = item
return obj
}, {} as Record<string, PlaygroundArticleT | undefined>)
const articles = [
actionsJsArticle,
actionsPyArticle,
codespacesJsArticle,
codespacesPyArticle,
codespacesJavaArticle,
codespacesNetArticle,
]
const codeLanguages: Array<CodeLanguage> = [
{
@@ -20,6 +27,14 @@ const codeLanguages: Array<CodeLanguage> = [
id: 'py',
label: 'Python',
},
{
id: 'dotnet',
label: 'C#',
},
{
id: 'java',
label: 'Java',
},
]
type PlaygroundContextT = {
@@ -48,11 +63,18 @@ export const PlaygroundContextProvider = (props: { children: React.ReactNode })
const router = useRouter()
const [activeSectionIndex, setActiveSectionIndex] = useState(0)
const [scrollToSection, setScrollToSection] = useState<number>()
const { langId } = router.query
const currentLanguage = codeLanguages.find(({ id }) => id === langId) || codeLanguages[0]
const availableLanguages = codeLanguages.filter(({ id }) => !!articlesByLangId[id])
const path = router.asPath.split('?')[0]
const relevantArticles = articles.filter(({ slug }) => slug === path)
const article = articlesByLangId[currentLanguage.id]
const { langId } = router.query
const availableLanguageIds = relevantArticles.map(({ codeLanguageId }) => codeLanguageId)
const currentLanguage =
codeLanguages.find(({ id }) => id === langId) ||
(codeLanguages.find(({ id }) => id === availableLanguageIds[0]) as CodeLanguage)
const article = relevantArticles.find(
({ codeLanguageId }) => codeLanguageId === currentLanguage?.id
)
const context = {
activeSectionIndex,
@@ -60,7 +82,7 @@ export const PlaygroundContextProvider = (props: { children: React.ReactNode })
scrollToSection,
setScrollToSection,
currentLanguage,
codeLanguages: availableLanguages,
codeLanguages: codeLanguages.filter(({ id }) => availableLanguageIds.includes(id)),
article,
}

View File

@@ -17,7 +17,7 @@ export type ArticleGuide = {
topics: Array<string>
}
export type ProductSubLandingContextT = {
export type ProductGuidesContextT = {
title: string
intro: string
featuredTrack?: FeaturedTrack
@@ -26,21 +26,21 @@ export type ProductSubLandingContextT = {
allTopics?: Array<string>
}
export const ProductSubLandingContext = createContext<ProductSubLandingContextT | null>(null)
export const ProductGuidesContext = createContext<ProductGuidesContextT | null>(null)
export const useProductSubLandingContext = (): ProductSubLandingContextT => {
const context = useContext(ProductSubLandingContext)
export const useProductGuidesContext = (): ProductGuidesContextT => {
const context = useContext(ProductGuidesContext)
if (!context) {
throw new Error(
'"useProductSubLandingContext" may only be used inside "ProductSubLandingContext.Provider"'
'"useProductGuidesContext" may only be used inside "ProductGuidesContext.Provider"'
)
}
return context
}
export const getProductSubLandingContextFromRequest = (req: any): ProductSubLandingContextT => {
export const getProductGuidesContextFromRequest = (req: any): ProductGuidesContextT => {
const page = req.context.page
return {

Some files were not shown because too many files have changed in this diff Show More