Merge branch 'main' into patch-1
3
.github/CODEOWNERS
vendored
@@ -27,6 +27,9 @@ package.json @github/docs-engineering
|
||||
# Content strategy
|
||||
/contributing/content-markup-reference.md @github/docs-content-strategy
|
||||
/contributing/content-style-guide.md @github/docs-content-strategy
|
||||
/contributing/content-model.md @github/docs-content-strategy
|
||||
/contributing/content-style-guide.md @github/docs-content-strategy
|
||||
/contributing/content-templates.md @github/docs-content-strategy
|
||||
|
||||
# Make sure that Octokit maintainers get notified about changes
|
||||
# relevant to the Octokit libraries (https://github.com/octokit)
|
||||
|
||||
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -24,7 +24,7 @@ Closes [issue link]
|
||||
|
||||
### Check off the following:
|
||||
|
||||
- [ ] I have reviewed my changes in staging (look for the **deploy-to-heroku** link in your pull request, then click **View deployment**).
|
||||
- [ ] I have reviewed my changes in staging (look for the latest deployment event in your pull request's timeline, then click **View deployment**).
|
||||
- [ ] For content changes, I have completed the [self-review checklist](https://github.com/github/docs/blob/main/CONTRIBUTING.md#self-review).
|
||||
|
||||
### Writer impact (This section is for GitHub staff members only):
|
||||
|
||||
1
.github/allowed-actions.js
vendored
@@ -10,7 +10,6 @@ module.exports = [
|
||||
"actions/labeler@5f867a63be70efff62b767459b009290364495eb", // v2.2.0
|
||||
"actions/setup-node@c46424eee26de4078d34105d3de3cc4992202b1e", // v2.1.4
|
||||
"actions/setup-python@dc73133d4da04e56a135ae2246682783cc7c7cb6", // v2.2.2
|
||||
"ruby/setup-ruby@fdcfbcf14ec9672f6f615cb9589a1bc5dd69d262", // v1.64.1
|
||||
"actions/stale@9d6f46564a515a9ea11e7762ab3957ee58ca50da", // v3.0.16
|
||||
"alex-page/github-project-automation-plus@fdb7991b72040d611e1123d2b75ff10eda9372c9",
|
||||
"andymckay/labeler@22d5392de2b725cea4b284df5824125054049d84",
|
||||
|
||||
201
.github/workflows/staging-deploy-pr.yml
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
name: Staging - Deploy PR
|
||||
|
||||
# **What it does**: To deploy PRs to a Heroku staging environment.
|
||||
# **Why we have it**: To deploy with high visibility in case of failures.
|
||||
# **Who does it impact**: All contributors.
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
- synchronize
|
||||
- unlocked
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
pullRequestUrl:
|
||||
description: 'Pull Request URL'
|
||||
required: true
|
||||
default: 'https://github.com/github/docs/pull/1234'
|
||||
forceRebuild:
|
||||
description: 'Force the Heroku App to be rebuilt from scratch? (true/false)'
|
||||
required: false
|
||||
default: 'false'
|
||||
|
||||
jobs:
|
||||
validate-inputs:
|
||||
if: ${{ github.repository == 'github/docs-internal' || github.repository == 'github/docs' }}
|
||||
name: Validate inputs
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 2
|
||||
outputs:
|
||||
headRef: ${{ steps.validate.outputs.headRef }}
|
||||
steps:
|
||||
- if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
name: Check out repo
|
||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
|
||||
with:
|
||||
# Enables cloning the Early Access repo later with the relevant PAT
|
||||
persist-credentials: 'false'
|
||||
|
||||
- if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
name: Setup node
|
||||
uses: actions/setup-node@c46424eee26de4078d34105d3de3cc4992202b1e
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
- if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
name: Get npm cache directory
|
||||
id: npm-cache
|
||||
run: |
|
||||
echo "::set-output name=dir::$(npm config get cache)"
|
||||
|
||||
- if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
name: Cache node modules
|
||||
uses: actions/cache@0781355a23dac32fd3bac414512f4b903437991a
|
||||
with:
|
||||
path: ${{ steps.npm-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-
|
||||
|
||||
- if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
name: Validate and get head.ref
|
||||
id: validate
|
||||
uses: actions/github-script@2b34a689ec86a68d8ab9478298f91d5401337b7d
|
||||
env:
|
||||
PR_URL: ${{ github.event.inputs.pullRequestUrl }}
|
||||
FORCE_REBUILD: ${{ github.event.inputs.forceRebuild }}
|
||||
with:
|
||||
script: |
|
||||
const parsePrUrl = require('./script/deployment/parse-pr-url')
|
||||
|
||||
// Manually resolve workflow_dispatch inputs
|
||||
const { PR_URL, FORCE_REBUILD } = process.env
|
||||
|
||||
if (!['true', 'false'].includes(FORCE_REBUILD)) {
|
||||
throw new Error(`'forceRebuild' input must be either 'true' or 'false' but was '${FORCE_REBUILD}'`)
|
||||
}
|
||||
|
||||
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 github.pulls.get({
|
||||
owner,
|
||||
repo,
|
||||
pull_number: pullNumber
|
||||
})
|
||||
|
||||
core.setOutput('headRef', pullRequest.head.ref)
|
||||
|
||||
deploy:
|
||||
if: ${{ github.repository == 'github/docs-internal' || github.repository == 'github/docs' }}
|
||||
needs: validate-inputs
|
||||
name: Deploy
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
concurrency:
|
||||
group: staging_${{ needs.validate-inputs.outputs.headRef || github.head_ref }}
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
|
||||
with:
|
||||
# Enables cloning the Early Access repo later with the relevant PAT
|
||||
persist-credentials: 'false'
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@c46424eee26de4078d34105d3de3cc4992202b1e
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
- name: Get npm cache directory
|
||||
id: npm-cache
|
||||
run: |
|
||||
echo "::set-output name=dir::$(npm config get cache)"
|
||||
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@0781355a23dac32fd3bac414512f4b903437991a
|
||||
with:
|
||||
path: ${{ steps.npm-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Deploy
|
||||
uses: actions/github-script@2b34a689ec86a68d8ab9478298f91d5401337b7d
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
HEROKU_API_TOKEN: ${{ secrets.HEROKU_API_TOKEN }}
|
||||
DOCUBOT_REPO_PAT: ${{ secrets.DOCUBOT_REPO_PAT }}
|
||||
HYDRO_ENDPOINT: ${{ secrets.HYDRO_ENDPOINT }}
|
||||
HYDRO_SECRET: ${{ secrets.HYDRO_SECRET }}
|
||||
PR_URL: ${{ github.event.inputs.pullRequestUrl }}
|
||||
FORCE_REBUILD: ${{ github.event.inputs.forceRebuild }}
|
||||
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!')
|
||||
}
|
||||
|
||||
const parsePrUrl = require('./script/deployment/parse-pr-url')
|
||||
const getOctokit = require('./script/helpers/github')
|
||||
const 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 {
|
||||
let pullRequest = null
|
||||
let forceRebuild = false
|
||||
|
||||
// Manually resolve workflow_dispatch inputs
|
||||
if (context.eventName === 'workflow_dispatch') {
|
||||
const { PR_URL, FORCE_REBUILD } = process.env
|
||||
|
||||
forceRebuild = FORCE_REBUILD === 'true'
|
||||
|
||||
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: pr } = await octokit.pulls.get({
|
||||
owner,
|
||||
repo,
|
||||
pull_number: pullNumber
|
||||
})
|
||||
pullRequest = pr
|
||||
}
|
||||
|
||||
await deployToStaging({
|
||||
herokuToken: HEROKU_API_TOKEN,
|
||||
octokit,
|
||||
pullRequest: pullRequest || context.payload.pull_request,
|
||||
forceRebuild,
|
||||
runId: context.runId
|
||||
})
|
||||
} catch (error) {
|
||||
console.error(`Failed to deploy to staging: ${error.message}`)
|
||||
console.error(error)
|
||||
throw error
|
||||
}
|
||||
88
.github/workflows/staging-undeploy-pr.yml
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
name: Staging - Undeploy PR
|
||||
|
||||
# **What it does**: To undeploy PRs from a Heroku staging environment, i.e. destroy the Heroku App.
|
||||
# **Why we have it**: To save money spent on deployments for closed PRs.
|
||||
# **Who does it impact**: All contributors.
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- closed
|
||||
- locked
|
||||
|
||||
jobs:
|
||||
undeploy:
|
||||
if: ${{ github.repository == 'github/docs-internal' || github.repository == 'github/docs' }}
|
||||
name: Undeploy
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 2
|
||||
concurrency:
|
||||
group: staging_${{ github.head_ref }}
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
|
||||
with:
|
||||
# Enables cloning the Early Access repo later with the relevant PAT
|
||||
persist-credentials: 'false'
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@c46424eee26de4078d34105d3de3cc4992202b1e
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
- name: Get npm cache directory
|
||||
id: npm-cache
|
||||
run: |
|
||||
echo "::set-output name=dir::$(npm config get cache)"
|
||||
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@0781355a23dac32fd3bac414512f4b903437991a
|
||||
with:
|
||||
path: ${{ steps.npm-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- 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!')
|
||||
}
|
||||
|
||||
const getOctokit = require('./script/helpers/github')
|
||||
const 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({
|
||||
herokuToken: HEROKU_API_TOKEN,
|
||||
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
|
||||
}
|
||||
@@ -102,7 +102,7 @@ jobs:
|
||||
|
||||
const badFiles = badFilesArr.join('\n')
|
||||
|
||||
let reviewMessage = `👋 Hey there spelunker. It looks like you've modified some files that we can't accept as contributions. The complete list of files we can't accept are:\n${badFiles}\n\nYou'll need to revert all of the files you changed in that list using [GitHub Desktop](https://docs.github.com/en/free-pro-team@latest/desktop/contributing-and-collaborating-using-github-desktop/reverting-a-commit) or \`git checkout origin/main <file name>\`. Once you get those files reverted, we can continue with the review process. :octocat:`
|
||||
let reviewMessage = `👋 Hey there spelunker. It looks like you've modified some files that we can't accept as contributions. The complete list of files we can't accept are:\n${badFiles}\n\nYou'll need to revert all of the files you changed in that list using [GitHub Desktop](https://docs.github.com/en/free-pro-team@latest/desktop/contributing-and-collaborating-using-github-desktop/managing-commits/reverting-a-commit) or \`git checkout origin/main <file name>\`. Once you get those files reverted, we can continue with the review process. :octocat:`
|
||||
|
||||
await github.pulls.createReview({
|
||||
...context.repo,
|
||||
|
||||
8
.github/workflows/update-graphql-files.yml
vendored
@@ -29,14 +29,6 @@ jobs:
|
||||
exit 1 # prevents further steps from running
|
||||
- name: Checkout
|
||||
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f
|
||||
- name: Set up Ruby
|
||||
uses: ruby/setup-ruby@fdcfbcf14ec9672f6f615cb9589a1bc5dd69d262
|
||||
with:
|
||||
ruby-version: '2.4'
|
||||
- name: Install Ruby dependencies
|
||||
run: |
|
||||
gem install bundler
|
||||
bundle install
|
||||
- name: Install Node.js dependencies
|
||||
run: npm ci
|
||||
- name: Run updater scripts
|
||||
|
||||
2
.github/workflows/workflow-lint.yml
vendored
@@ -26,4 +26,4 @@ jobs:
|
||||
- name: Run linter
|
||||
uses: cschleiden/actions-linter@0ff16d6ac5103cca6c92e6cbc922b646baaea5be
|
||||
with:
|
||||
workflows: '[".github/workflows/*.yml"]'
|
||||
workflows: '[".github/workflows/*.yml", "!.github/workflows/staging-deploy-pr.yml", "!.github/workflows/staging-undeploy-pr.yml"]'
|
||||
|
||||
5
Gemfile
@@ -1,5 +0,0 @@
|
||||
source 'http://rubygems.org'
|
||||
# ruby '2.4'
|
||||
|
||||
gem 'graphql', '1.10.6'
|
||||
gem 'graphql-schema_comparator', '~> 1.0.0'
|
||||
20
Gemfile.lock
@@ -1,20 +0,0 @@
|
||||
GEM
|
||||
remote: http://rubygems.org/
|
||||
specs:
|
||||
graphql (1.10.6)
|
||||
graphql-schema_comparator (1.0.0)
|
||||
bundler (>= 1.14)
|
||||
graphql (~> 1.10)
|
||||
thor (>= 0.19, < 2.0)
|
||||
thor (1.0.1)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
x86_64-linux
|
||||
|
||||
DEPENDENCIES
|
||||
graphql (= 1.10.6)
|
||||
graphql-schema_comparator (~> 1.0.0)
|
||||
|
||||
BUNDLED WITH
|
||||
2.2.1
|
||||
BIN
assets/images/help/desktop/amend-commit-context-menu.png
Normal file
|
After Width: | Height: | Size: 224 KiB |
BIN
assets/images/help/desktop/amend-last-commit-overview.png
Normal file
|
After Width: | Height: | Size: 210 KiB |
|
After Width: | Height: | Size: 130 KiB |
|
After Width: | Height: | Size: 58 KiB |
BIN
assets/images/help/desktop/reorder-drag-and-drop.png
Normal file
|
After Width: | Height: | Size: 364 KiB |
BIN
assets/images/help/desktop/reorder-force-push-dialog.png
Normal file
|
After Width: | Height: | Size: 92 KiB |
BIN
assets/images/help/desktop/reorder-merge-commit-dialog.png
Normal file
|
After Width: | Height: | Size: 48 KiB |
BIN
assets/images/help/desktop/reorder-resolve-conflicts.png
Normal file
|
After Width: | Height: | Size: 85 KiB |
BIN
assets/images/help/desktop/reorder-stash-dialog.png
Normal file
|
After Width: | Height: | Size: 65 KiB |
BIN
assets/images/help/desktop/squash-and-merge-menu.png
Normal file
|
After Width: | Height: | Size: 205 KiB |
BIN
assets/images/help/desktop/squash-and-merge-selection.png
Normal file
|
After Width: | Height: | Size: 71 KiB |
BIN
assets/images/help/desktop/squash-drag-and-drop.png
Normal file
|
After Width: | Height: | Size: 200 KiB |
BIN
assets/images/help/desktop/squash-force-push.png
Normal file
|
After Width: | Height: | Size: 93 KiB |
BIN
assets/images/help/desktop/squash-merge-commit-dialog.png
Normal file
|
After Width: | Height: | Size: 49 KiB |
BIN
assets/images/help/desktop/squash-multiple-commits.png
Normal file
|
After Width: | Height: | Size: 136 KiB |
BIN
assets/images/help/desktop/squash-stash-dialog.png
Normal file
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 224 KiB |
|
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 137 KiB |
BIN
assets/images/help/repository/fetch-and-merge-button.png
Normal file
|
After Width: | Height: | Size: 189 KiB |
BIN
assets/images/help/repository/fetch-upstream-drop-down.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
@@ -11,7 +11,7 @@ import { useTranslation } from './hooks/useTranslation'
|
||||
|
||||
type Props = { children?: React.ReactNode }
|
||||
export const DefaultLayout = (props: Props) => {
|
||||
const { builtAssets, page, error, isHomepageVersion } = useMainContext()
|
||||
const { page, error, isHomepageVersion } = useMainContext()
|
||||
const { t } = useTranslation('errors')
|
||||
return (
|
||||
<div className="d-lg-flex">
|
||||
@@ -22,8 +22,6 @@ export const DefaultLayout = (props: Props) => {
|
||||
<title>{page.fullTitle}</title>
|
||||
) : null}
|
||||
|
||||
<script src={builtAssets.main.js} />
|
||||
|
||||
{/* For Google and Bots */}
|
||||
{page.introPlainText && <meta name="description" content={page.introPlainText} />}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ export const Header = () => {
|
||||
style={{ zIndex: 2 }}
|
||||
>
|
||||
{/* desktop header */}
|
||||
<div className="d-none d-lg-flex flex-justify-end">
|
||||
<div className="d-none d-lg-flex flex-justify-end" data-testid="desktop-header">
|
||||
{showVersionPicker && (
|
||||
<div className="py-2 mr-4">
|
||||
<HomepageVersionPicker />
|
||||
@@ -54,7 +54,7 @@ export const Header = () => {
|
||||
</div>
|
||||
|
||||
{/* mobile header */}
|
||||
<div className="d-lg-none">
|
||||
<div className="d-lg-none" data-testid="mobile-header">
|
||||
<div className="d-flex flex-justify-between">
|
||||
<div className="d-flex flex-items-center" id="github-logo-mobile" role="banner">
|
||||
<Link aria-hidden="true" tabIndex={-1} href={`/${router.locale}`}>
|
||||
@@ -71,6 +71,7 @@ export const Header = () => {
|
||||
|
||||
<div>
|
||||
<ButtonOutline
|
||||
data-testid="mobile-menu-button"
|
||||
css
|
||||
onClick={() => setIsMenuOpen(!isMenuOpen)}
|
||||
aria-label="Navigation Menu"
|
||||
|
||||
@@ -32,7 +32,7 @@ export const LanguagePicker = ({ variant }: Props) => {
|
||||
<Link
|
||||
key={lang.code}
|
||||
href={router.asPath}
|
||||
locale={lang.hreflang}
|
||||
locale={lang.code}
|
||||
className={cx(
|
||||
'd-block py-2',
|
||||
lang.code === router.locale
|
||||
@@ -71,7 +71,7 @@ export const LanguagePicker = ({ variant }: Props) => {
|
||||
{langs.map((lang) => {
|
||||
return (
|
||||
<Dropdown.Item key={lang.code}>
|
||||
<Link href={router.asPath} locale={lang.hreflang}>
|
||||
<Link href={router.asPath} locale={lang.code}>
|
||||
{lang.nativeName ? (
|
||||
<>
|
||||
{lang.nativeName} ({lang.name})
|
||||
|
||||
16
components/PrintAction.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
import React from 'react'
|
||||
|
||||
type Props = {
|
||||
children: React.ReactElement
|
||||
}
|
||||
export function PrintAction({ children }: Props) {
|
||||
const onClick = () => {
|
||||
try {
|
||||
document.execCommand('print', false)
|
||||
} catch (e) {
|
||||
window.print()
|
||||
}
|
||||
}
|
||||
|
||||
return React.cloneElement(React.Children.only(children), { onClick })
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import { useTranslation } from 'components/hooks/useTranslation'
|
||||
import { sendEvent, EventType } from '../javascripts/events'
|
||||
import { useMainContext } from './context/MainContext'
|
||||
import { useVersion } from 'components/hooks/useVersion'
|
||||
import cx from 'classnames'
|
||||
|
||||
type SearchResult = {
|
||||
url: string
|
||||
@@ -22,7 +23,8 @@ type Props = {
|
||||
// Homepage and 404 should be `isStandalone`, all others not
|
||||
// `updateSearchParams` should be false on the GraphQL explorer page
|
||||
export function Search({ isStandalone = false, updateSearchParams = true, children }: Props) {
|
||||
const [query, setQuery] = useState('')
|
||||
const router = useRouter()
|
||||
const [query, setQuery] = useState(router.query.query || '')
|
||||
const [results, setResults] = useState<Array<SearchResult>>([])
|
||||
const [activeHit, setActiveHit] = useState(0)
|
||||
const inputRef = useRef<HTMLInputElement>(null)
|
||||
@@ -31,18 +33,14 @@ export function Search({ isStandalone = false, updateSearchParams = true, childr
|
||||
|
||||
// Figure out language and version for index
|
||||
const { languages, searchVersions, nonEnterpriseDefaultVersion } = useMainContext()
|
||||
const router = useRouter()
|
||||
// fall back to the non-enterprise default version (FPT currently) on the homepage, 404 page, etc.
|
||||
const version = searchVersions[currentVersion] || searchVersions[nonEnterpriseDefaultVersion]
|
||||
const language = (Object.keys(languages).includes(router.locale || '') && router.locale) || 'en'
|
||||
|
||||
// If the user shows up with a query in the URL, go ahead and search for it
|
||||
useEffect(() => {
|
||||
const params = new URLSearchParams(location.search)
|
||||
if (params.has('query')) {
|
||||
const xquery = params.get('query')?.trim() || ''
|
||||
setQuery(xquery)
|
||||
/* await */ fetchSearchResults(xquery)
|
||||
if (router.query.query) {
|
||||
/* await */ fetchSearchResults((router.query.query as string).trim())
|
||||
}
|
||||
}, [])
|
||||
|
||||
@@ -182,7 +180,7 @@ export function Search({ isStandalone = false, updateSearchParams = true, childr
|
||||
</div>
|
||||
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
|
||||
<div
|
||||
className={'search-overlay-desktop' + (!isStandalone && query ? ' js-open' : '')}
|
||||
className={cx('search-overlay-desktop', !isStandalone && query ? 'js-open' : '')}
|
||||
onClick={closeSearch}
|
||||
></div>
|
||||
</>
|
||||
@@ -193,8 +191,9 @@ export function Search({ isStandalone = false, updateSearchParams = true, childr
|
||||
<div className="ais-SearchBox">
|
||||
<form role="search" className="ais-SearchBox-form" noValidate onSubmit={preventRefresh}>
|
||||
<input
|
||||
data-testid="site-search-input"
|
||||
ref={inputRef}
|
||||
className={'ais-SearchBox-input' + (isStandalone || query ? ' js-open' : '')}
|
||||
className={cx('ais-SearchBox-input', isStandalone || query ? 'js-open' : '')}
|
||||
type="search"
|
||||
placeholder={t`placeholder`}
|
||||
/* eslint-disable-next-line jsx-a11y/no-autofocus */
|
||||
|
||||
@@ -55,6 +55,7 @@ export const SidebarNav = () => {
|
||||
width: 280px;
|
||||
height: 100vh;
|
||||
flex-shrink: 0;
|
||||
padding-bottom: 32px;
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
|
||||
@@ -35,7 +35,7 @@ export const Survey = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<form className="f5" onSubmit={submit} ref={formRef}>
|
||||
<form className="f5" onSubmit={submit} ref={formRef} data-testid="survey-form">
|
||||
<h2 className="mb-1 f4">
|
||||
{t`able_to_find`}
|
||||
|
||||
@@ -128,7 +128,7 @@ export const Survey = () => {
|
||||
</>
|
||||
)}
|
||||
|
||||
{state === ViewState.END && <p className="color-text-secondary f6">{t`feedback`}</p>}
|
||||
{state === ViewState.END && <p className="color-text-secondary f6" data-testid="survey-end">{t`feedback`}</p>}
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { Tooltip } from '@primer/components'
|
||||
import { PrinterIcon } from './PrinterIcon'
|
||||
|
||||
import { PrintAction } from 'components/PrintAction'
|
||||
|
||||
type Props = {
|
||||
children: React.ReactNode
|
||||
}
|
||||
@@ -10,18 +12,11 @@ export const ArticleTitle = ({ children }: Props) => {
|
||||
<h1 className="my-4 border-bottom-0">{children}</h1>
|
||||
<div className="d-none d-lg-block ml-2">
|
||||
<Tooltip aria-label="Print this article" noDelay direction="n">
|
||||
<button
|
||||
className="btn-link Link--muted"
|
||||
onClick={() => {
|
||||
try {
|
||||
document.execCommand('print', false)
|
||||
} catch (e) {
|
||||
window.print()
|
||||
}
|
||||
}}
|
||||
>
|
||||
<PrinterIcon />
|
||||
</button>
|
||||
<PrintAction>
|
||||
<button className="btn-link Link--muted">
|
||||
<PrinterIcon />
|
||||
</button>
|
||||
</PrintAction>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -68,7 +68,6 @@ export type MainContextT = {
|
||||
maptopic?: BreadcrumbT
|
||||
article?: BreadcrumbT
|
||||
}
|
||||
builtAssets: { main: { js: string } }
|
||||
activeProducts: Array<ProductT>
|
||||
currentProduct?: ProductT
|
||||
currentLayoutName: string
|
||||
@@ -112,13 +111,12 @@ export type MainContextT = {
|
||||
|
||||
export const getMainContextFromRequest = (req: any): MainContextT => {
|
||||
return {
|
||||
builtAssets: { main: { js: req.context.builtAssets.main.js } },
|
||||
breadcrumbs: req.context.breadcrumbs || {},
|
||||
activeProducts: req.context.activeProducts,
|
||||
currentProduct: req.context.productMap[req.context.currentProduct] || null,
|
||||
currentLayoutName: req.context.currentLayoutName,
|
||||
isHomepageVersion: req.context.currentVersion === 'homepage',
|
||||
error: req.context.error || '',
|
||||
error: req.context.error ? req.context.error.toString() : '',
|
||||
data: {
|
||||
ui: req.context.site.data.ui,
|
||||
reusables: {
|
||||
|
||||
@@ -79,7 +79,7 @@ export const getFeaturedLinksFromReq = (req: any): Record<string, Array<Featured
|
||||
Object.entries(req.context.featuredLinks || {}).map(([key, entries]) => {
|
||||
return [
|
||||
key,
|
||||
(entries as Array<any> || []).map((entry: any) => ({
|
||||
((entries as Array<any>) || []).map((entry: any) => ({
|
||||
href: entry.href,
|
||||
title: entry.title,
|
||||
intro: entry.intro,
|
||||
|
||||
@@ -5,7 +5,7 @@ export type FeaturedTrack = {
|
||||
trackName: string
|
||||
title: string
|
||||
description: string
|
||||
guides?: Array<{ href: string; page: { type: string }; title: string; intro: string }>
|
||||
guides?: Array<{ href: string; page?: { type: string }; title: string; intro: string }>
|
||||
} | null
|
||||
|
||||
export type ArticleGuide = {
|
||||
@@ -60,7 +60,10 @@ export const getProductSubLandingContextFromRequest = (req: any): ProductSubLand
|
||||
}),
|
||||
})),
|
||||
includeGuides: (page.includeGuides || []).map((guide: any) => {
|
||||
return pick(guide, ['href', 'title', 'intro', 'type', 'topics'])
|
||||
return {
|
||||
...pick(guide, ['href', 'title', 'intro', 'topics']),
|
||||
type: guide.type || ''
|
||||
}
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ export const ArticleList = ({
|
||||
</div>
|
||||
)}
|
||||
|
||||
<ul className="list-style-none">
|
||||
<ul className="list-style-none" data-testid="article-list">
|
||||
{articles.map((link) => {
|
||||
return (
|
||||
<li key={link.href} className={cx(variant === 'compact' && 'border-top')}>
|
||||
|
||||
@@ -9,6 +9,7 @@ export const CodeExampleCard = ({ example }: Props) => {
|
||||
return (
|
||||
<a
|
||||
className="Box d-flex flex-column flex-justify-between height-full color-shadow-medium hover-shadow-large no-underline color-text-primary"
|
||||
data-testid="code-example-card"
|
||||
href={`https://github.com/${example.href}`}
|
||||
>
|
||||
<div className="p-4">
|
||||
|
||||
@@ -32,6 +32,7 @@ export const CodeExamples = () => {
|
||||
<div>
|
||||
<div className="pr-lg-3 mb-5 mt-3">
|
||||
<input
|
||||
data-testid="code-examples-input"
|
||||
className="input-lg py-2 px-3 col-12 col-lg-8 form-control"
|
||||
placeholder={t('search_code_examples')}
|
||||
type="search"
|
||||
@@ -53,6 +54,7 @@ export const CodeExamples = () => {
|
||||
|
||||
{numVisible < productCodeExamples.length && !isSearching && (
|
||||
<button
|
||||
data-testid="code-examples-show-more"
|
||||
className="btn btn-outline float-right"
|
||||
onClick={() => setNumVisible(numVisible + PAGE_SIZE)}
|
||||
>
|
||||
@@ -61,7 +63,10 @@ export const CodeExamples = () => {
|
||||
)}
|
||||
|
||||
{isSearching && searchResults.length === 0 && (
|
||||
<div className="py-4 text-center color-text-secondary font-mktg">
|
||||
<div
|
||||
data-testid="code-examples-no-results"
|
||||
className="py-4 text-center color-text-secondary font-mktg"
|
||||
>
|
||||
<div className="mb-3">
|
||||
<SearchIcon size={24} />{' '}
|
||||
</div>
|
||||
|
||||
@@ -12,7 +12,13 @@ export const LandingSection = ({ title, children, className, sectionLink, descri
|
||||
<div className={cx('container-xl px-3 px-md-6', className)} id={sectionLink}>
|
||||
{title && (
|
||||
<h2 className={cx('font-mktg h1 color-text-primary', !description ? 'mb-3' : 'mb-4')}>
|
||||
{sectionLink ? <a className="color-unset" href={`#${sectionLink}`}>{title}</a> : title}
|
||||
{sectionLink ? (
|
||||
<a className="color-unset" href={`#${sectionLink}`}>
|
||||
{title}
|
||||
</a>
|
||||
) : (
|
||||
title
|
||||
)}
|
||||
</h2>
|
||||
)}
|
||||
{description && (
|
||||
|
||||
@@ -16,7 +16,7 @@ export const ProductArticlesList = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="d-flex gutter flex-wrap">
|
||||
<div className="d-flex gutter flex-wrap" data-testid="product-articles-list">
|
||||
{currentProductTree.childPages.map((treeNode, i) => {
|
||||
if (treeNode.page.documentType === 'article') {
|
||||
return null
|
||||
@@ -34,7 +34,9 @@ const ProductTreeNodeList = ({ treeNode }: { treeNode: ProductTreeNode }) => {
|
||||
return (
|
||||
<div className="col-12 col-lg-4 mb-6 height-full">
|
||||
<h4 className="mb-3">
|
||||
<Link className="color-unset" href={treeNode.href}>{treeNode.renderedFullTitle}</Link>
|
||||
<Link className="color-unset" href={treeNode.href}>
|
||||
{treeNode.renderedFullTitle}
|
||||
</Link>
|
||||
</h4>
|
||||
|
||||
<ul className="list-style-none">
|
||||
|
||||
@@ -37,7 +37,11 @@ export const ProductLanding = () => {
|
||||
</LandingSection>
|
||||
|
||||
{productCodeExamples.length > 0 && (
|
||||
<LandingSection title={t('code_examples')} sectionLink="code-examples" className="my-6 pb-6">
|
||||
<LandingSection
|
||||
title={t('code_examples')}
|
||||
sectionLink="code-examples"
|
||||
className="my-6 pb-6"
|
||||
>
|
||||
<CodeExamples />
|
||||
</LandingSection>
|
||||
)}
|
||||
@@ -68,7 +72,7 @@ export const ProductLanding = () => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
<LandingSection title={`All ${shortTitle} docs`} sectionLink="all-docs" className="pt-9">
|
||||
<LandingSection title={`All ${shortTitle} docs`} sectionLink="all-docs" className="pt-9">
|
||||
<ProductArticlesList />
|
||||
</LandingSection>
|
||||
</DefaultLayout>
|
||||
|
||||
@@ -6,6 +6,7 @@ import { PatchNotes } from './PatchNotes'
|
||||
import { Link } from 'components/Link'
|
||||
import { CurrentVersion, ReleaseNotePatch, GHESMessage } from './types'
|
||||
import { useOnScreen } from 'components/hooks/useOnScreen'
|
||||
import { PrintAction } from 'components/PrintAction'
|
||||
|
||||
type Props = {
|
||||
patch: ReleaseNotePatch
|
||||
@@ -65,7 +66,9 @@ export function GHESReleaseNotePatch({
|
||||
</Link>
|
||||
)}
|
||||
|
||||
<button className="js-print btn-link ml-3 text-small text-bold">Print</button>
|
||||
<PrintAction>
|
||||
<button className="btn-link ml-3 text-small text-bold">Print</button>
|
||||
</PrintAction>
|
||||
</div>
|
||||
|
||||
<p className="color-text-secondary mt-1">{dayjs(patch.date).format('MMMM, DD, YYYY')}</p>
|
||||
|
||||
@@ -36,7 +36,7 @@ export function GHESReleaseNotes({ context }: Props) {
|
||||
{prevRelease ? (
|
||||
<Link
|
||||
className="btn btn-outline"
|
||||
href={`/${currentLanguage}/${currentVersion.plan}@${prevRelease}/${currentProduct}/release-notes`}
|
||||
href={`/${currentLanguage}/${currentVersion.plan}@${prevRelease}/${currentProduct?.id}/release-notes`}
|
||||
>
|
||||
<ChevronLeftIcon /> {prevRelease}
|
||||
</Link>
|
||||
@@ -51,7 +51,7 @@ export function GHESReleaseNotes({ context }: Props) {
|
||||
{nextRelease ? (
|
||||
<Link
|
||||
className="btn btn-outline"
|
||||
href={`/${currentLanguage}/${currentVersion.plan}@${nextRelease}/${currentProduct}/release-notes`}
|
||||
href={`/${currentLanguage}/${currentVersion.plan}@${nextRelease}/${currentProduct?.id}/release-notes`}
|
||||
>
|
||||
{nextRelease} <ChevronRightIcon />
|
||||
</Link>
|
||||
|
||||
@@ -7,16 +7,17 @@ type Props = {
|
||||
|
||||
export const ArticleCard = ({ card, typeLabel }: Props) => {
|
||||
return (
|
||||
<div className="d-flex col-12 col-md-4 pr-0 pr-md-6 pr-lg-8">
|
||||
<div data-testid="article-card" className="d-flex col-12 col-md-4 pr-0 pr-md-6 pr-lg-8">
|
||||
<a className="no-underline d-flex flex-column py-3 border-bottom" href={card.href}>
|
||||
<h4 className="h4 color-text-primary mb-1">{card.title}</h4>
|
||||
<div className="h6 text-uppercase">{typeLabel}</div>
|
||||
<div className="h6 text-uppercase" data-testid="article-card-type">{typeLabel}</div>
|
||||
<p className="color-text-secondary my-3">{card.intro}</p>
|
||||
{card.topics.length > 0 && (
|
||||
<div>
|
||||
{card.topics.map((topic) => {
|
||||
return (
|
||||
<span
|
||||
data-testid="article-card-topic"
|
||||
key={topic}
|
||||
className="IssueLabel bg-gradient--pink-blue color-text-inverse mr-1"
|
||||
>
|
||||
|
||||
@@ -50,6 +50,7 @@ export const ArticleCards = () => {
|
||||
className="form-select f4 text-bold border-0 rounded-0 border-top box-shadow-none pl-0"
|
||||
name="type"
|
||||
aria-label="guide types"
|
||||
data-testid="card-filter-dropdown"
|
||||
onChange={onChangeTypeFilter}
|
||||
>
|
||||
<option value="">{t('filters.all')}</option>
|
||||
@@ -70,6 +71,7 @@ export const ArticleCards = () => {
|
||||
value={topicFilter}
|
||||
className="form-select f4 text-bold border-0 rounded-0 border-top box-shadow-none pl-0"
|
||||
name="topics"
|
||||
data-testid="card-filter-dropdown"
|
||||
aria-label="guide topics"
|
||||
onChange={onChangeTopicFilter}
|
||||
>
|
||||
|
||||
@@ -7,17 +7,17 @@ type Props = {
|
||||
track: FeaturedTrack
|
||||
}
|
||||
|
||||
const MAX_VISIBLE_GUIDES = 4
|
||||
const DEFAULT_VISIBLE_GUIDES = 4
|
||||
export const LearningTrack = ({ track }: Props) => {
|
||||
const [visibleGuides, setVisibleGuides] = useState(track?.guides?.slice(0, 4))
|
||||
const [numVisible, setNumVisible] = useState(DEFAULT_VISIBLE_GUIDES)
|
||||
const showAll = () => {
|
||||
setVisibleGuides(track?.guides)
|
||||
setNumVisible(track?.guides?.length || 0)
|
||||
}
|
||||
const { t } = useTranslation('product_sublanding')
|
||||
|
||||
return (
|
||||
<div className="my-3 px-4 col-12 col-md-6 learning-track">
|
||||
<div className="Box js-show-more-container d-flex flex-column">
|
||||
<div className="Box d-flex flex-column">
|
||||
<div className="Box-header bg-gradient--blue-pink p-4 d-flex flex-1 flex-items-start flex-wrap">
|
||||
<div className="d-flex flex-auto flex-items-start col-8 col-md-12 col-xl-8">
|
||||
<div className="my-xl-0 mr-xl-3">
|
||||
@@ -38,10 +38,11 @@ export const LearningTrack = ({ track }: Props) => {
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
{visibleGuides?.map((guide) => (
|
||||
<div>
|
||||
|
||||
{track?.guides?.slice(0, numVisible).map((guide) => (
|
||||
<div key={guide.href + track?.trackName}>
|
||||
<a
|
||||
className="Box-row d-flex flex-items-center color-text-primary no-underline js-show-more-item"
|
||||
className="Box-row d-flex flex-items-center color-text-primary no-underline"
|
||||
href={`${guide.href}?learn=${track?.trackName}`}
|
||||
>
|
||||
<div className="circle color-bg-tertiary d-inline-flex mr-4">
|
||||
@@ -53,27 +54,28 @@ export const LearningTrack = ({ track }: Props) => {
|
||||
</div>
|
||||
<h5 className="flex-auto pr-2">{guide.title}</h5>
|
||||
<div className="color-text-tertiary h6 text-uppercase flex-shrink-0">
|
||||
{t('guide_types')[guide.page.type]}
|
||||
{t('guide_types')[guide.page?.type || '']}
|
||||
</div>
|
||||
</a>
|
||||
{track?.guides && track?.guides?.indexOf(guide) + 1 === MAX_VISIBLE_GUIDES ? (
|
||||
<button
|
||||
className="Box-footer btn-link border-top-0 position-relative text-center text-bold color-text-link pt-1 pb-3 col-12 js-show-more-button"
|
||||
onClick={showAll}
|
||||
>
|
||||
<div
|
||||
className="position-absolute left-0 right-0 py-5 fade-background-bottom"
|
||||
style={{ bottom: '50px' }}
|
||||
></div>
|
||||
<span>
|
||||
Show {track?.guides?.length - MAX_VISIBLE_GUIDES} {t(`more_guides`)}
|
||||
</span>
|
||||
</button>
|
||||
) : (
|
||||
<div />
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
|
||||
{(track?.guides?.length || 0) > numVisible ? (
|
||||
<button
|
||||
className="Box-footer btn-link border-top-0 position-relative text-center text-bold color-text-link pt-1 pb-3 col-12"
|
||||
onClick={showAll}
|
||||
>
|
||||
<div
|
||||
className="position-absolute left-0 right-0 py-5 fade-background-bottom"
|
||||
style={{ bottom: '50px' }}
|
||||
></div>
|
||||
<span>
|
||||
Show {(track?.guides?.length || 0) - numVisible} {t(`more_guides`)}
|
||||
</span>
|
||||
</button>
|
||||
) : (
|
||||
<div />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -26,7 +26,7 @@ export const SubLandingHero = () => {
|
||||
)}
|
||||
</div>
|
||||
<div className="color-text-tertiary h6 text-uppercase">
|
||||
{t('guide_types')[guide.page.type]}
|
||||
{t('guide_types')[guide.page?.type || '']}
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="font-mktg h3-mktg my-4 color-text-primary">{guide.title}</h3>
|
||||
|
||||
@@ -397,17 +397,22 @@ jobs:
|
||||
|
||||
## Publishing to package registries
|
||||
|
||||
You can configure your workflow to publish your Python package to any package registry you'd like when your CI tests pass.
|
||||
You can configure your workflow to publish your Python package to a package registry once your CI tests pass. This section demonstrates how you can use {% data variables.product.prodname_actions %} to upload your package to PyPI each time you [publish a release](/github/administering-a-repository/managing-releases-in-a-repository).
|
||||
|
||||
You can store any access tokens or credentials needed to publish your package using secrets. The following example creates and publishes a package to PyPI using `twine` and `dist`. For more information, see "[Creating and using encrypted secrets](/github/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets)."
|
||||
For this example, you will need to create two [PyPI API tokens](https://pypi.org/help/#apitoken). You can use secrets to store the access tokens or credentials needed to publish your package. For more information, see "[Creating and using encrypted secrets](/github/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets)."
|
||||
|
||||
{% raw %}
|
||||
```yaml{:copy}
|
||||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
|
||||
name: Upload Python Package
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [created]
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
@@ -421,14 +426,14 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install setuptools wheel twine
|
||||
- name: Build and publish
|
||||
env:
|
||||
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
|
||||
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
|
||||
run: |
|
||||
python setup.py sdist bdist_wheel
|
||||
twine upload dist/*
|
||||
pip install build
|
||||
- name: Build package
|
||||
run: python -m build
|
||||
- name: Publish package
|
||||
uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
|
||||
with:
|
||||
user: __token__
|
||||
password: ${{ secrets.PYPI_API_TOKEN }}
|
||||
```
|
||||
{% endraw %}
|
||||
|
||||
|
||||
@@ -100,7 +100,6 @@ children:
|
||||
- /deploying-to-amazon-elastic-container-service
|
||||
- /deploying-to-azure-app-service
|
||||
- /deploying-to-google-kubernetes-engine
|
||||
- /deploying-to-google-kubernetes-engine
|
||||
- /using-github-actions-for-project-management
|
||||
- /closing-inactive-issues
|
||||
- /scheduling-issue-creation
|
||||
|
||||
@@ -36,8 +36,9 @@ We recommend that you have a basic understanding of workflow configuration optio
|
||||
You might also find it helpful to have a basic understanding of the following:
|
||||
|
||||
- "[Encrypted secrets](/actions/reference/encrypted-secrets)"
|
||||
- "[Authentication in a workflow](/actions/reference/authentication-in-a-workflow)"
|
||||
- "[Working with the Docker registry](/packages/working-with-a-github-packages-registry/working-with-the-docker-registry)"
|
||||
- "[Authentication in a workflow](/actions/reference/authentication-in-a-workflow)"{% if currentVersion == "free-pro-team@latest" %}
|
||||
- "[Working with the {% data variables.product.prodname_container_registry %}](/packages/working-with-a-github-packages-registry/working-with-the-container-registry)"{% else %}
|
||||
- "[Working with the Docker registry](/packages/working-with-a-github-packages-registry/working-with-the-docker-registry)"{% endif %}
|
||||
|
||||
## About image configuration
|
||||
|
||||
@@ -63,9 +64,11 @@ The `build-push-action` options required for Docker Hub are:
|
||||
* `tags`: The tag of your new image in the format `DOCKER-HUB-NAMESPACE/DOCKER-HUB-REPOSITORY:VERSION`. You can set a single tag as shown below, or specify multiple tags in a list.
|
||||
* `push`: If set to `true`, the image will be pushed to the registry if it is built successfully.
|
||||
|
||||
{% raw %}
|
||||
```yaml{:copy}
|
||||
name: Publish Docker image
|
||||
|
||||
{% data reusables.actions.actions-not-certified-by-github %}
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
@@ -79,35 +82,50 @@ jobs:
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
username: {% raw %}${{ secrets.DOCKER_USERNAME }}{% endraw %}
|
||||
password: {% raw %}${{ secrets.DOCKER_PASSWORD }}{% endraw %}
|
||||
- name: Push to Docker Hub
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
push: true
|
||||
tags: my-docker-hub-namespace/my-docker-hub-repository:latest
|
||||
```
|
||||
{% endraw %}
|
||||
|
||||
{% data reusables.github-actions.docker-tag-with-ref %}
|
||||
The above workflow checks out the {% data variables.product.prodname_dotcom %} repository, uses the `login-action` to log in to the registry, and then uses the `build-push-action` action to: build a Docker image based on your repository's `Dockerfile`; push the image to Docker Hub, and apply a tag to the image.
|
||||
|
||||
## Publishing images to {% data variables.product.prodname_registry %}
|
||||
|
||||
{% data reusables.github-actions.release-trigger-workflow %}
|
||||
|
||||
In the example workflow below, we use the Docker `login-action` and `build-push-action` actions to build the Docker image, and if the build succeeds, push the built image to {% data variables.product.prodname_registry %}.
|
||||
In the example workflow below, we use the Docker `login-action`{% if currentVersion == "free-pro-team@latest" %}, `metadata-action`,{% endif %} and `build-push-action` actions to build the Docker image, and if the build succeeds, push the built image to {% data variables.product.prodname_registry %}.
|
||||
|
||||
The `login-action` options required for {% data variables.product.prodname_registry %} are:
|
||||
* `registry`: Must be set to `docker.pkg.github.com`.
|
||||
* `registry`: Must be set to {% if currentVersion == "free-pro-team@latest" %}`ghcr.io`{% else %}`docker.pkg.github.com`{% endif %}.
|
||||
* `username`: You can use the {% raw %}`${{ github.actor }}`{% endraw %} context to automatically use the username of the user that triggered the workflow run. For more information, see "[Context and expression syntax for GitHub Actions](/actions/reference/context-and-expression-syntax-for-github-actions#github-context)."
|
||||
* `password`: You can use the automatically-generated `GITHUB_TOKEN` secret for the password. For more information, see "[Authenticating with the GITHUB_TOKEN](/actions/automating-your-workflow-with-github-actions/authenticating-with-the-github_token)."
|
||||
|
||||
The `build-push-action` options required for {% data variables.product.prodname_registry %} are:
|
||||
* `tags`: Must be set in the format `docker.pkg.github.com/OWNER/REPOSITORY/IMAGE_NAME:VERSION`. For example, for an image named `octo-image` stored on {% data variables.product.prodname_dotcom %} at `http://github.com/octo-org/octo-repo`, the `tags` option should be set to `docker.pkg.github.com/octo-org/octo-repo/octo-image:latest`. You can set a single tag as shown below, or specify multiple tags in a list.
|
||||
* `push`: If set to `true`, the image will be pushed to the registry if it is built successfully.
|
||||
{% if currentVersion == "free-pro-team@latest" %}
|
||||
The `metadata-action` option required for {% data variables.product.prodname_registry %} is:
|
||||
* `images`: The namespace and name for the Docker image you are building.
|
||||
{% endif %}
|
||||
|
||||
The `build-push-action` options required for {% data variables.product.prodname_registry %} are:{% if currentVersion == "free-pro-team@latest" %}
|
||||
* `context`: Defines the build's context as the set of files located in the specified path.{% endif %}
|
||||
* `push`: If set to `true`, the image will be pushed to the registry if it is built successfully.{% if currentVersion == "free-pro-team@latest" %}
|
||||
* `tags` and `labels`: These are populated by output from `metadata-action`.{% else %}
|
||||
* `tags`: Must be set in the format `docker.pkg.github.com/OWNER/REPOSITORY/IMAGE_NAME:VERSION`. For example, for an image named `octo-image` stored on {% data variables.product.prodname_dotcom %} at `http://github.com/octo-org/octo-repo`, the `tags` option should be set to `docker.pkg.github.com/octo-org/octo-repo/octo-image:latest`. You can set a single tag as shown below, or specify multiple tags in a list.{% endif %}
|
||||
|
||||
{% if currentVersion == "free-pro-team@latest" %}
|
||||
{% data reusables.package_registry.publish-docker-image %}
|
||||
|
||||
The above workflow if triggered by a push to the "release" branch. It checks out the GitHub repository, and uses the `login-action` to log in to the {% data variables.product.prodname_container_registry %}. It then extracts labels and tags for the Docker image. Finally, it and uses the `build-push-action` action to build the image and publish it on the {% data variables.product.prodname_container_registry %}.
|
||||
|
||||
{% else %}
|
||||
```yaml{:copy}
|
||||
name: Publish Docker image
|
||||
|
||||
{% data reusables.actions.actions-not-certified-by-github %}
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
@@ -133,10 +151,11 @@ jobs:
|
||||
push: true
|
||||
tags: |
|
||||
{% if currentVersion == "github-ae@latest" %}docker.YOUR-HOSTNAME.com{% else %}docker.pkg.github.com{% endif %}{% raw %}/${{ github.repository }}/octo-image:${{ github.sha }}{% endraw %}
|
||||
{% if currentVersion == "github-ae@latest" %}docker.YOUR-HOSTNAME.com{% else %}docker.pkg.github.com{% endif %}{% raw %}/${{ github.repository }}/octo-image:${{ github.ref }}{% endraw %}
|
||||
{% if currentVersion == "github-ae@latest" %}docker.YOUR-HOSTNAME.com{% else %}docker.pkg.github.com{% endif %}{% raw %}/${{ github.repository }}/octo-image:${{ github.event.release.tag_name }}{% endraw %}
|
||||
```
|
||||
|
||||
{% data reusables.github-actions.docker-tag-with-ref %}
|
||||
The above workflow checks out the {% data variables.product.prodname_dotcom %} repository, uses the `login-action` to log in to the registry, and then uses the `build-push-action` action to: build a Docker image based on your repository's `Dockerfile`; push the image to the Docker registry, and apply the commit SHA and release version as image tags.
|
||||
{% endif %}
|
||||
|
||||
## Publishing images to Docker Hub and {% data variables.product.prodname_registry %}
|
||||
|
||||
@@ -144,8 +163,13 @@ In a single workflow, you can publish your Docker image to multiple registries b
|
||||
|
||||
The following example workflow uses the steps from the previous sections ("[Publishing images to Docker Hub](#publishing-images-to-docker-hub)" and "[Publishing images to {% data variables.product.prodname_registry %}](#publishing-images-to-github-packages)") to create a single workflow that pushes to both registries.
|
||||
|
||||
|
||||
|
||||
```yaml{:copy}
|
||||
name: Publish Docker image
|
||||
|
||||
{% data reusables.actions.actions-not-certified-by-github %}
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
@@ -164,22 +188,33 @@ jobs:
|
||||
with:
|
||||
username: {% raw %}${{ secrets.DOCKER_USERNAME }}{% endraw %}
|
||||
password: {% raw %}${{ secrets.DOCKER_PASSWORD }}{% endraw %}
|
||||
- name: Log in to GitHub Docker Registry
|
||||
- name: Log in to the {% if currentVersion == "free-pro-team@latest" %}Container{% else %}Docker{% endif %} registry
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
registry: {% if currentVersion == "github-ae@latest" %}docker.YOUR-HOSTNAME.com{% else %}docker.pkg.github.com{% endif %}
|
||||
registry: {% if currentVersion == "free-pro-team@latest" %}ghcr.io{% elsif currentVersion == "github-ae@latest" %}docker.YOUR-HOSTNAME.com{% else %}docker.pkg.github.com{% endif %}
|
||||
username: {% raw %}${{ github.actor }}{% endraw %}
|
||||
password: {% raw %}${{ secrets.GITHUB_TOKEN }}{% endraw %}
|
||||
- name: Push to Docker Hub
|
||||
- name: Build and push to Docker Hub
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
push: true
|
||||
tags: my-docker-hub-namespace/my-docker-hub-repository:{% raw %}${{ github.ref }}{% endraw %}
|
||||
- name: Build container image
|
||||
tags: my-docker-hub-namespace/my-docker-hub-repository:{% raw %}${{ github.event.release.tag_name }}{% endraw %}{% if currentVersion == "free-pro-team@latest" %}
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@v3
|
||||
with:
|
||||
images: ghcr.io/{% raw %}${{ github.repository }}{% endraw %}{% endif %}
|
||||
- name: Build and push to {% data variables.product.prodname_registry %}
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
push: true
|
||||
tags: {% if currentVersion == "github-ae@latest" %}docker.YOUR-HOSTNAME.com{% else %}docker.pkg.github.com{% endif %}{% raw %}/${{ github.repository }}/my-image:${{ github.ref }}{% endraw %}
|
||||
push: true{% if currentVersion == "free-pro-team@latest" %}
|
||||
context: .
|
||||
tags: {% raw %}${{ steps.meta.outputs.tags }}{% endraw %}
|
||||
labels: {% raw %}${{ steps.meta.outputs.labels }}{% endraw %}{% else %}
|
||||
tags: {% if currentVersion == "github-ae@latest" %}docker.YOUR-HOSTNAME.com{% else %}docker.pkg.github.com{% endif %}{% raw %}/${{ github.repository }}/my-image:${{ github.event.release.tag_name }}{% endraw %}{% endif %}
|
||||
```
|
||||
|
||||
The above workflow checks out the {% data variables.product.prodname_dotcom %} repository, uses the `login-action` twice to log in to both registries, and then uses the `build-push-action` action twice to build and push the Docker image to Docker Hub and {% data variables.product.prodname_registry %}. For both steps, it tags the built Docker image with the Git reference of the workflow event. This workflow is triggered on publishing a {% data variables.product.prodname_dotcom %} release, so the reference for both registries will be the Git tag for the release.
|
||||
The above workflow checks out the {% data variables.product.prodname_dotcom %} repository, uses the `login-action` twice to log in to both registries, and then uses the `build-push-action` action twice to build and push the Docker image to Docker Hub and the
|
||||
{% if currentVersion == "free-pro-team@latest" %}{% data variables.product.prodname_container_registry %}. For Docker Hub, it tags the built Docker image with the version tag for the release that triggered the workflow. For the {% data variables.product.prodname_container_registry %}, tags and labels are automatically generated by the `metadata-action` action.
|
||||
{% else %}Docker registry. For both steps, it tags the built Docker image with the version tag for the release that triggered the workflow.
|
||||
{% endif %}
|
||||
|
||||
@@ -79,16 +79,16 @@ jobs:
|
||||
issues: write {% endif %}
|
||||
steps:
|
||||
- name: Create issue using REST API
|
||||
run: {% raw %}|
|
||||
run: |
|
||||
curl --request POST \
|
||||
--url https://api.github.com/repos/${{ github.repository }}/issues \
|
||||
--header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' \
|
||||
--url {% data variables.product.api_url_code %}/repos/${% raw %}{{ github.repository }}{% endraw %}/issues \
|
||||
--header 'authorization: Bearer ${% raw %}{{ secrets.GITHUB_TOKEN }}{% endraw %}' \
|
||||
--header 'content-type: application/json' \
|
||||
--data '{
|
||||
"title": "Automated issue for commit: ${{ github.sha }}",
|
||||
"body": "This issue was automatically created by the GitHub Action workflow **${{ github.workflow }}**. \n\n The commit hash was: _${{ github.sha }}_."
|
||||
"title": "Automated issue for commit: ${% raw %}{{ github.sha }}{% endraw %}",
|
||||
"body": "This issue was automatically created by the GitHub Action workflow **${% raw %}{{ github.workflow }}{% endraw %}**. \n\n The commit hash was: _${% raw %}{{ github.sha }}{% endraw %}_."
|
||||
}' \
|
||||
--fail{% endraw %}
|
||||
--fail
|
||||
```
|
||||
|
||||
## Permissions for the `GITHUB_TOKEN`
|
||||
|
||||
@@ -84,7 +84,7 @@ You must have administrative access on your IdP to configure the application for
|
||||
|
||||
| Value | Other names | Description | Example |
|
||||
| :- | :- | :- | :- |
|
||||
| URL | Tenant URL | URL to the SCIM provisioning API for your enterprise on {% data variables.product.prodname_ghe_managed %} | <pre>https://api.<em>YOUR-GITHUB-AE-HOSTNAME</em>/scim/v2</pre> |
|
||||
| URL | Tenant URL | URL to the SCIM provisioning API for your enterprise on {% data variables.product.prodname_ghe_managed %} | <nobr><code>{% data variables.product.api_url_pre %}</nobr></code> |
|
||||
| Shared secret | Personal access token, secret token | Token for application on your IdP to perform provisioning tasks on behalf of an enterprise owner | Personal access token you created in step 1 |
|
||||
|
||||
{% endif %}
|
||||
|
||||
@@ -4,7 +4,6 @@ intro: 'If you purchase additional storage and bandwidth for {% data variables.l
|
||||
redirect_from:
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/about-billing-for-git-large-file-storage
|
||||
- /articles/about-billing-for-git-large-file-storage
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/about-billing-for-git-large-file-storage
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/managing-billing-for-git-large-file-storage/about-billing-for-git-large-file-storage
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -6,7 +6,6 @@ redirect_from:
|
||||
- /articles/downgrading-storage-and-bandwidth-for-a-personal-account/
|
||||
- /articles/downgrading-storage-and-bandwidth-for-an-organization/
|
||||
- /articles/downgrading-git-large-file-storage
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/downgrading-git-large-file-storage
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/managing-billing-for-git-large-file-storage/downgrading-git-large-file-storage
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -6,7 +6,6 @@ redirect_from:
|
||||
- /articles/purchasing-additional-storage-and-bandwidth-for-a-personal-account/
|
||||
- /articles/purchasing-additional-storage-and-bandwidth-for-an-organization/
|
||||
- /articles/upgrading-git-large-file-storage
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/upgrading-git-large-file-storage
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/managing-billing-for-git-large-file-storage/upgrading-git-large-file-storage
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -6,7 +6,6 @@ redirect_from:
|
||||
- /articles/viewing-storage-and-bandwidth-usage-for-a-personal-account/
|
||||
- /articles/viewing-storage-and-bandwidth-usage-for-an-organization/
|
||||
- /articles/viewing-your-git-large-file-storage-usage
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/viewing-your-git-large-file-storage-usage
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/managing-billing-for-git-large-file-storage/viewing-your-git-large-file-storage-usage
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -4,7 +4,6 @@ intro: 'If you install a paid app in {% data variables.product.prodname_marketpl
|
||||
redirect_from:
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/about-billing-for-github-marketplace
|
||||
- /articles/about-billing-for-github-marketplace
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/about-billing-for-github-marketplace
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/managing-billing-for-github-marketplace-apps/about-billing-for-github-marketplace
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -6,7 +6,6 @@ redirect_from:
|
||||
- /articles/canceling-an-app-for-your-personal-account/
|
||||
- /articles/canceling-an-app-for-your-organization/
|
||||
- /articles/canceling-a-github-marketplace-app
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/canceling-a-github-marketplace-app
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/managing-billing-for-github-marketplace-apps/canceling-a-github-marketplace-app
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -6,7 +6,6 @@ redirect_from:
|
||||
- /articles/downgrading-an-app-for-your-personal-account/
|
||||
- /articles/downgrading-an-app-for-your-organization/
|
||||
- /articles/downgrading-the-billing-plan-for-a-github-marketplace-app
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/downgrading-the-billing-plan-for-a-github-marketplace-app
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/managing-billing-for-github-marketplace-apps/downgrading-the-billing-plan-for-a-github-marketplace-app
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -6,7 +6,6 @@ redirect_from:
|
||||
- /articles/upgrading-an-app-for-your-personal-account/
|
||||
- /articles/upgrading-an-app-for-your-organization/
|
||||
- /articles/upgrading-the-billing-plan-for-a-github-marketplace-app
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/upgrading-the-billing-plan-for-a-github-marketplace-app
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/managing-billing-for-github-marketplace-apps/upgrading-the-billing-plan-for-a-github-marketplace-app
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -20,7 +20,7 @@ topics:
|
||||
|
||||
{% note %}
|
||||
|
||||
**Billing update for container image storage:** During the beta phase of the {% data variables.product.prodname_container_registry %}, Docker image storage and bandwidth are free for both the previous `docker.pkg.github.com` and current `ghcr.io` hosting services. For more information, see "[Introduction to {% data variables.product.prodname_registry %}](/packages/learn-github-packages/introduction-to-github-packages)."
|
||||
**Billing update for container image storage:** The period of free use for container image storage and bandwidth for the {% data variables.product.prodname_container_registry %} has been extended. If you are using {% data variables.product.prodname_container_registry %} you'll be informed at least one month in advance of billing commencing and you'll be given an estimate of how much you should expect to pay. For more information about the {% data variables.product.prodname_container_registry %}, see "[Working with the Container registry](/packages/working-with-a-github-packages-registry/working-with-the-container-registry)."
|
||||
|
||||
{% endnote %}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ intro: You will be billed for your sponsorships with the rest of your paid produ
|
||||
redirect_from:
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/about-billing-for-github-sponsors
|
||||
- /articles/about-billing-for-github-sponsors
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/about-billing-for-github-sponsors
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/managing-billing-for-github-sponsors/about-billing-for-github-sponsors
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -4,7 +4,6 @@ intro: You can downgrade your sponsorship to a lower tier or cancel your sponsor
|
||||
redirect_from:
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/downgrading-a-sponsorship
|
||||
- /articles/downgrading-a-sponsorship
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/downgrading-a-sponsorship
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/managing-billing-for-github-sponsors/downgrading-a-sponsorship
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -4,7 +4,6 @@ intro: You can upgrade your sponsorship to a higher tier.
|
||||
redirect_from:
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/upgrading-a-sponsorship
|
||||
- /articles/upgrading-a-sponsorship
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/upgrading-a-sponsorship
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/managing-billing-for-github-sponsors/upgrading-a-sponsorship
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -11,7 +11,6 @@ redirect_from:
|
||||
- /articles/organization-billing-plans/
|
||||
- /articles/github-s-billing-plans
|
||||
- /articles/about-billing-for-github-accounts
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/about-billing-for-github-accounts
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/managing-billing-for-your-github-account/about-billing-for-github-accounts
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -4,7 +4,6 @@ intro: 'With per-user pricing, organizations pay based on team size to access ad
|
||||
redirect_from:
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/about-per-user-pricing
|
||||
- /articles/about-per-user-pricing
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/about-per-user-pricing
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/managing-billing-for-your-github-account/about-per-user-pricing
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -7,7 +7,6 @@ redirect_from:
|
||||
- /articles/discounted-organization-accounts/
|
||||
- /articles/discounted-billing-plans/
|
||||
- /articles/discounted-subscriptions-for-github-accounts
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/discounted-subscriptions-for-github-accounts
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/managing-billing-for-your-github-account/discounted-subscriptions-for-github-accounts
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -16,7 +16,6 @@ redirect_from:
|
||||
- /articles/downgrading-your-organization-from-github-business-cloud-to-the-team-plan/
|
||||
- /articles/downgrading-your-github-billing-plan/
|
||||
- /articles/downgrading-your-github-subscription
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/downgrading-your-github-subscription
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/managing-billing-for-your-github-account/downgrading-your-github-subscription
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -4,7 +4,6 @@ intro: 'When you upgrade the subscription for your personal account or organizat
|
||||
redirect_from:
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/how-does-upgrading-or-downgrading-affect-the-billing-process
|
||||
- /articles/how-does-upgrading-or-downgrading-affect-the-billing-process
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/how-does-upgrading-or-downgrading-affect-the-billing-process
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/managing-billing-for-your-github-account/how-does-upgrading-or-downgrading-affect-the-billing-process
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -18,7 +18,6 @@ redirect_from:
|
||||
- /articles/adding-seats-to-your-organization/
|
||||
- /articles/upgrading-your-github-billing-plan/
|
||||
- /articles/upgrading-your-github-subscription
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/upgrading-your-github-subscription
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/managing-billing-for-your-github-account/upgrading-your-github-subscription
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -7,7 +7,6 @@ redirect_from:
|
||||
- /articles/viewing-and-managing-pending-changes-to-your-organization-s-billing-plan/
|
||||
- /articles/viewing-and-managing-pending-changes-to-your-billing-plan/
|
||||
- /articles/viewing-and-managing-pending-changes-to-your-subscription
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/viewing-and-managing-pending-changes-to-your-subscription
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/managing-billing-for-your-github-account/viewing-and-managing-pending-changes-to-your-subscription
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -4,7 +4,6 @@ intro: 'Everything you purchase on {% data variables.product.prodname_dotcom %}
|
||||
redirect_from:
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/about-billing-on-github
|
||||
- /articles/about-billing-on-github
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/about-billing-on-github
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/managing-your-github-billing-settings/about-billing-on-github
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -12,7 +12,6 @@ redirect_from:
|
||||
- /articles/how-can-i-add-extra-information-to-my-organization-s-receipts/
|
||||
- /articles/adding-information-to-your-organization-s-receipts/
|
||||
- /articles/adding-information-to-your-receipts
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/adding-information-to-your-receipts
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/managing-your-github-billing-settings/adding-information-to-your-receipts
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -16,7 +16,6 @@ redirect_from:
|
||||
- /articles/updating-your-organization-s-payment-method/
|
||||
- /articles/switching-payment-methods-for-your-organization/
|
||||
- /articles/adding-or-editing-a-payment-method
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/adding-or-editing-a-payment-method
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/managing-your-github-billing-settings/adding-or-editing-a-payment-method
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -7,7 +7,6 @@ redirect_from:
|
||||
- /articles/switching-between-monthly-and-yearly-billing-for-your-personal-account/
|
||||
- /articles/switching-between-monthly-and-yearly-billing-for-your-organization/
|
||||
- /articles/changing-the-duration-of-your-billing-cycle
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/changing-the-duration-of-your-billing-cycle
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/managing-your-github-billing-settings/changing-the-duration-of-your-billing-cycle
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -7,7 +7,6 @@ redirect_from:
|
||||
- /articles/redeeming-a-coupon-for-your-personal-account/
|
||||
- /articles/redeeming-a-coupon-for-organizations/
|
||||
- /articles/redeeming-a-coupon
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/redeeming-a-coupon
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/managing-your-github-billing-settings/redeeming-a-coupon
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -8,7 +8,6 @@ redirect_from:
|
||||
- /articles/removing-a-credit-card-associated-with-your-organization/
|
||||
- /articles/removing-a-payment-method-associated-with-your-organization/
|
||||
- /articles/removing-a-payment-method
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/removing-a-payment-method
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/managing-your-github-billing-settings/removing-a-payment-method
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -8,7 +8,6 @@ redirect_from:
|
||||
- '/articles/how-do-i-change-the-billing-email,setting-your-billing-email/'
|
||||
- /articles/setting-your-organization-s-billing-email/
|
||||
- /articles/setting-your-billing-email
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/setting-your-billing-email
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/managing-your-github-billing-settings/setting-your-billing-email
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -5,7 +5,6 @@ redirect_from:
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/troubleshooting-a-declined-credit-card-charge
|
||||
- /articles/what-do-i-do-if-my-card-is-declined/
|
||||
- /articles/troubleshooting-a-declined-credit-card-charge
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/troubleshooting-a-declined-credit-card-charge
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/managing-your-github-billing-settings/troubleshooting-a-declined-credit-card-charge
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -10,7 +10,6 @@ redirect_from:
|
||||
- /articles/unlocking-a-locked-personal-account/
|
||||
- /articles/unlocking-a-locked-organization-account/
|
||||
- /articles/unlocking-a-locked-account
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/unlocking-a-locked-account
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/managing-your-github-billing-settings/unlocking-a-locked-account
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -7,7 +7,6 @@ redirect_from:
|
||||
- /articles/downloading-receipts-for-personal-accounts/
|
||||
- /articles/downloading-receipts-for-organizations/
|
||||
- /articles/viewing-your-payment-history-and-receipts
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/viewing-your-payment-history-and-receipts
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/managing-your-github-billing-settings/viewing-your-payment-history-and-receipts
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -5,7 +5,6 @@ redirect_from:
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/about-organizations-for-procurement-companies
|
||||
- /articles/about-organizations-for-resellers/
|
||||
- /articles/about-organizations-for-procurement-companies
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/about-organizations-for-procurement-companies
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/setting-up-paid-organizations-for-procurement-companies/about-organizations-for-procurement-companies
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -4,7 +4,6 @@ intro: 'You can create and pay for a {% data variables.product.prodname_dotcom %
|
||||
redirect_from:
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/creating-and-paying-for-an-organization-on-behalf-of-a-client
|
||||
- /articles/creating-and-paying-for-an-organization-on-behalf-of-a-client
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/creating-and-paying-for-an-organization-on-behalf-of-a-client
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/setting-up-paid-organizations-for-procurement-companies/creating-and-paying-for-an-organization-on-behalf-of-a-client
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -5,7 +5,6 @@ redirect_from:
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/renewing-your-clients-paid-organization
|
||||
- /articles/renewing-your-client-s-paid-organization
|
||||
- /articles/renewing-your-clients-paid-organization
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/renewing-your-clients-paid-organization
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/setting-up-paid-organizations-for-procurement-companies/renewing-your-clients-paid-organization
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -5,7 +5,6 @@ redirect_from:
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/upgrading-or-downgrading-your-clients-paid-organization
|
||||
- /articles/upgrading-or-downgrading-your-client-s-paid-organization
|
||||
- /articles/upgrading-or-downgrading-your-clients-paid-organization
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/upgrading-or-downgrading-your-clients-paid-organization
|
||||
- /github/setting-up-and-managing-billing-and-payments-on-github/setting-up-paid-organizations-for-procurement-companies/upgrading-or-downgrading-your-clients-paid-organization
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
|
||||
@@ -134,7 +134,7 @@ updates:
|
||||
|
||||
### `schedule.interval`
|
||||
|
||||
**Required**. You must define how often to check for new versions for each package manager. By default, this is at 5am UTC. To modify this, use [`schedule.time`](#scheduletime) and [`schedule.timezone`](#scheduletimezone).
|
||||
**Required**. You must define how often to check for new versions for each package manager. By default, {% data variables.product.prodname_dependabot %} randomly assigns a time to apply all the updates in the configuration file. To set a specific time, you can use [`schedule.time`](#scheduletime) and [`schedule.timezone`](#scheduletimezone).
|
||||
|
||||
- `daily`—runs on every weekday, Monday to Friday.
|
||||
- `weekly`—runs once each week. By default, this is on Monday. To modify this, use [`schedule.day`](#scheduleday).
|
||||
|
||||
@@ -79,3 +79,7 @@ When creating a secret in an organization, you can use a policy to limit which r
|
||||
The name of the secret is listed on the Dependabot secrets page. You can click **Update** to change the secret value or its access policy. You can click **Remove** to delete the secret.
|
||||
|
||||

|
||||
|
||||
## Adding {% data variables.product.prodname_dependabot %} to your registries IP allow list
|
||||
|
||||
If your private registry is configured with an IP allow list, you can find the IP addresses {% data variables.product.prodname_dependabot %} uses to access the registry in the meta API endpoint, under the `dependabot` key. For more information, see "[Meta](/rest/reference/meta)."
|
||||
|
||||
@@ -9,7 +9,7 @@ topics:
|
||||
|
||||
{% data reusables.codespaces.release-stage %}
|
||||
|
||||
When you enable access and security for a repository owned by your user account, any codespaces that are created for that repository will have read and write permissions to all other repositories you own. If you want to restrict the repositories a codespace can access, you can limit to it to either the repository the codespace was opened for or specific repositories. You should only enable access and security for repositories you trust.
|
||||
When you enable access and security for a repository owned by your user account, any codespaces that are created for that repository will have read permissions to all other repositories you own. If you want to restrict the repositories a codespace can access, you can limit to it to either the repository the codespace was opened for or specific repositories. You should only enable access and security for repositories you trust.
|
||||
|
||||
{% data reusables.user_settings.access_settings %}
|
||||
{% data reusables.user_settings.codespaces-tab %}
|
||||
|
||||
@@ -9,6 +9,7 @@ versions:
|
||||
children:
|
||||
- /adding-and-cloning-repositories
|
||||
- /making-changes-in-a-branch
|
||||
- /managing-commits
|
||||
- /working-with-your-remote-repository-on-github-or-github-enterprise
|
||||
- /keeping-your-local-repository-in-sync-with-github
|
||||
---
|
||||
|
||||
@@ -71,6 +71,19 @@ Some workflows require or benefit from rebasing instead of merging. By rebasing
|
||||
|
||||
{% endwindows %}
|
||||
|
||||
## Squashing and merging another branch into your project branch
|
||||
|
||||
1. Use the **Branch** drop-down and click **Squash and Merge into Current Branch**.
|
||||

|
||||
2. Click the branch you want to merge into the current branch, then click **Squash and merge**.
|
||||

|
||||
{% note %}
|
||||
|
||||
**Note:** If there are merge conflicts, {% data variables.product.prodname_desktop %} will warn you above the **Squash and merge** button. You will not be able to squash and merge the branch until you have resolved all conflicts.
|
||||
|
||||
{% endnote %}
|
||||
{% data reusables.desktop.push-origin %}
|
||||
|
||||
## Further Reading
|
||||
- "[Pull](/github/getting-started-with-github/github-glossary#pull)" in the {% data variables.product.prodname_dotcom %} glossary
|
||||
- "[Merge](/github/getting-started-with-github/github-glossary#merge)" in the {% data variables.product.prodname_dotcom %} glossary
|
||||
|
||||
@@ -100,14 +100,14 @@ Once you're satisfied with the changes you've chosen to include in your commit,
|
||||
|
||||
{% note %}
|
||||
|
||||
**Note**: {% data reusables.desktop.tags-push-with-commits %} For more information, see "[Managing tags](/desktop/contributing-to-projects/managing-tags)."
|
||||
**Note**: {% data reusables.desktop.tags-push-with-commits %} For more information, see "[Managing tags](/desktop/contributing-and-collaborating-using-github-desktop/managing-commits/managing-tags)."
|
||||
|
||||
{% endnote %}
|
||||
|
||||
{% data reusables.desktop.commit-message %}
|
||||
|
||||

|
||||
2. Optionally, to attribute a commit to another author, click the add co-authors icon and type the username(s) you want to include.
|
||||
1. Optionally, to attribute a commit to another author, click the add co-authors icon and type the username(s) you want to include.
|
||||
|
||||

|
||||
{% data reusables.desktop.commit-button %}
|
||||
|
||||
@@ -9,10 +9,7 @@ children:
|
||||
- /managing-branches
|
||||
- /committing-and-reviewing-changes-to-your-project
|
||||
- /stashing-changes
|
||||
- /pushing-changes-to-github
|
||||
- /reverting-a-commit
|
||||
- /cherry-picking-a-commit
|
||||
- /managing-tags
|
||||
- /viewing-the-branch-history
|
||||
- /pushing-changes-to-github
|
||||
---
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@ You can use branches to safely experiment with changes to your project. Branches
|
||||
|
||||
You always create a branch from an existing branch. Typically, you might create a branch from the default branch of your repository. You can then work on this new branch in isolation from changes that other people are making to the repository.
|
||||
|
||||
You can also create a branch starting from a previous commit in a branch's history. This can be helpful if you need to return to an earlier view of the repository to investigate a bug, or to create a hot fix on top of your latest release.
|
||||
|
||||
Once you're satisfied with your work, you can create a pull request to merge your changes in the current branch into another branch. For more information, see "[Creating an issue or pull request](/desktop/contributing-to-projects/creating-an-issue-or-pull-request)" and "[About pull requests](/articles/about-pull-requests)."
|
||||
|
||||
You can always create a branch in {% data variables.product.prodname_desktop %} if you have read access to a repository, but you can only push the branch to {% data variables.product.prodname_dotcom %} if you have write access to the repository.
|
||||
@@ -58,6 +60,15 @@ You can always create a branch in {% data variables.product.prodname_desktop %}
|
||||
|
||||
{% endwindows %}
|
||||
|
||||
## Creating a branch from a previous commit
|
||||
|
||||
{% data reusables.desktop.history-tab %}
|
||||
2. Right-click on the commit you would like to create a new branch from and select **Create Branch from Commit**.
|
||||

|
||||
{% data reusables.desktop.name-branch %}
|
||||
{% data reusables.desktop.confirm-new-branch-button %}
|
||||

|
||||
|
||||
## Publishing a branch
|
||||
|
||||
If you create a branch on {% data variables.product.product_name %}, you'll need to publish the branch to make it available for collaboration on {% data variables.product.prodname_dotcom %}.
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
title: Amending a commit
|
||||
intro: 'You can use {% data variables.product.prodname_desktop %} to amend your last commit.'
|
||||
versions:
|
||||
free-pro-team: '*'
|
||||
---
|
||||
|
||||
## About amending a commit
|
||||
|
||||
Amending a commit is a way to modify the most recent commit you have made in your current branch. This can be helpful if you need to edit the commit message or if you forgot to include changes in the commit.
|
||||
|
||||
You can continue to amend a commit until you push it to the remote repository. After you push a commit, the option to amend it is disabled in {% data variables.product.prodname_desktop %}. When you amend a commit, you replace the previous commit with a new commit to your current branch. Amending a commit that has been pushed to the remote repository could cause confusion for other collaborators working with the repository.
|
||||
|
||||
## Amending a commit
|
||||
|
||||
{% data reusables.desktop.history-tab %}
|
||||
2. Right-click on the most recent commit and select **Amend commit**.
|
||||

|
||||
3. Click the **Summary** field to modify the commit message. Optionally, you can modify or add information about the commit in the **Description** field.
|
||||
4. Select any uncommitted changes that you would like to add to the commit. For more information about selecting changes, see "[Committing and reviewing changes to your project](/desktop/contributing-and-collaborating-using-github-desktop/making-changes-in-a-branch/committing-and-reviewing-changes-to-your-project#selecting-changes-to-include-in-a-commit)."
|
||||
5. Once you have finalized your changes, click **Amend last commit**.
|
||||

|
||||