Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# ---------------------------------------------------------------
# To update the sha:
# https://github.com/github/gh-base-image/pkgs/container/gh-base-image%2Fgh-base-noble
FROM ghcr.io/github/gh-base-image/gh-base-noble:20250805-204228-g50c20871f AS base
FROM ghcr.io/github/gh-base-image/gh-base-noble:20250911-223345-ge6d335835 AS base

# Install curl for Node install and determining the early access branch
# Install git for cloning docs-early-access & translations repos
Expand Down
4 changes: 2 additions & 2 deletions data/reusables/actions/larger-runners-table.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
| Runner Size | Architecture| Processor (CPU)| Memory (RAM) | Storage (SSD) | Workflow label |
| ------------| ------------| -------------- | ------------- | ------------- |--------------------------------------------------------------------------------------------------------------------------------------------------|
| Large | Intel | 12 | 30 GB | 14 GB | <code>macos-latest-large</code>, <code>macos-13-large</code>, <code>macos-14-large</code> [latest], <code>macos-15-large</code> |
| XLarge | arm64 (M2) | 5 (+ 8 GPU hardware acceleration) | 14 GB | 14 GB | <code>macos-latest-xlarge</code>, <code>macos-13-xlarge</code>, <code>macos-14-xlarge</code> [latest], <code>macos-15-xlarge</code> |
| Large | Intel | 12 | 30 GB | 14 GB | <code>macos-latest-large</code>, <code>macos-13-large</code>, <code>macos-14-large</code>, <code>macos-15-large</code> (latest) |
| XLarge | arm64 (M2) | 5 (+ 8 GPU hardware acceleration) | 14 GB | 14 GB | <code>macos-latest-xlarge</code>, <code>macos-13-xlarge</code>, <code>macos-14-xlarge</code>, <code>macos-15-xlarge</code> (latest), <code>macos-26-xlarge</code> ({% data variables.release-phases.public_preview %}) |
14 changes: 8 additions & 6 deletions data/reusables/actions/supported-github-runners.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,10 @@ For public repositories, jobs using the workflow labels shown in the table below
<td>14 GB</td>
<td> arm64 </td>
<td>
<code><a href="https://github.com/actions/runner-images/blob/main/images/macos/macos-14-Readme.md">macos-latest</a></code>,
<code><a href="https://github.com/actions/runner-images/blob/main/images/macos/macos-14-Readme.md">macos-14</a></code>,
<code><a href="https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md">macos-15</a></code>
<code><a href="https://github.com/actions/runner-images/blob/main/images/macos/macos-15-arm64-Readme.md">macos-latest</a></code>,
<code><a href="https://github.com/actions/runner-images/blob/main/images/macos/macos-14-arm64-Readme.md">macos-14</a></code>,
<code><a href="https://github.com/actions/runner-images/blob/main/images/macos/macos-15-arm64-Readme.md">macos-15</a></code>,
<code><a href="https://github.com/actions/runner-images/blob/main/images/macos/macos-26-arm64-Readme.md">macos-26</a></code> ({% data variables.release-phases.public_preview %})
</td>
</tr>
</tbody>
Expand Down Expand Up @@ -142,9 +143,10 @@ For {% ifversion ghec %}internal and{% endif %} private repositories, jobs using
<td>14 GB</td>
<td> arm64 </td>
<td>
<code><a href="https://github.com/actions/runner-images/blob/main/images/macos/macos-14-Readme.md">macos-latest</a></code>,
<code><a href="https://github.com/actions/runner-images/blob/main/images/macos/macos-14-Readme.md">macos-14</a></code>,
<code><a href="https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md">macos-15</a></code>
<code><a href="https://github.com/actions/runner-images/blob/main/images/macos/macos-15-arm64-Readme.md">macos-latest</a></code>,
<code><a href="https://github.com/actions/runner-images/blob/main/images/macos/macos-14-arm64-Readme.md">macos-14</a></code>,
<code><a href="https://github.com/actions/runner-images/blob/main/images/macos/macos-15-arm64-Readme.md">macos-15</a></code>,
<code><a href="https://github.com/actions/runner-images/blob/main/images/macos/macos-26-arm64-Readme.md">macos-26</a></code> ({% data variables.release-phases.public_preview %})
</td>
</tr>
</tbody>
Expand Down
2 changes: 1 addition & 1 deletion data/reusables/copilot/grok-promo-period.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
> [!Important] Complimentary access for {% data variables.copilot.copilot_grok_code %} is available until 12 p.m. PDT on Wednesday, September 10, 2025. [Regular pricing](/copilot/reference/ai-models/supported-models#model-multipliers) applies after that point.
> [!Important] Complimentary access to {% data variables.copilot.copilot_grok_code %} is continuing past the previously announced end time. A new end date has not been set. We may update or conclude this promotion at any time. [Regular pricing](/copilot/reference/ai-models/supported-models#model-multipliers) applies after the extension ends.
64 changes: 50 additions & 14 deletions src/links/scripts/rendered-content-link-checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,12 @@ type Options = {
bail?: boolean
commentLimitToExternalLinks?: boolean
actionContext?: any
concurrency?: number
}

// Default concurrency limit for URL requests
const DEFAULT_CONCURRENCY_LIMIT = 3

const STATIC_PREFIXES: Record<string, string> = {
assets: path.resolve('assets'),
public: path.resolve(path.join('src', 'graphql', 'data')),
Expand Down Expand Up @@ -114,6 +118,32 @@ const externalLinkCheckerDB = await JSONFilePreset<Data>(EXTERNAL_LINK_CHECKER_D

type DBType = typeof externalLinkCheckerDB

// Simple concurrency limiter
async function limitConcurrency<T, R>(
items: T[],
asyncFn: (item: T) => Promise<R>,
limit: number = 3,
): Promise<R[]> {
const results: Promise<R>[] = []
const executing = new Set<Promise<R>>()

for (const item of items) {
const promise = asyncFn(item).then((result) => {
executing.delete(promise)
return result
})

results.push(promise)
executing.add(promise)

if (executing.size >= limit) {
await Promise.race(executing)
}
}

return Promise.all(results)
}

// Given a number and a percentage, return the same number with a *percentage*
// max change of making a bit larger or smaller.
// E.g. `jitter(55, 10)` will return a value between `[55 - 55/10: 55 + 55/10]`
Expand Down Expand Up @@ -156,6 +186,7 @@ if (import.meta.url.endsWith(process.argv[1])) {
REPORT_LABEL,
EXTERNAL_SERVER_ERRORS_AS_WARNINGS,
CHECK_ANCHORS,
CONCURRENCY,
} = process.env

const octokit = github()
Expand Down Expand Up @@ -193,6 +224,7 @@ if (import.meta.url.endsWith(process.argv[1])) {
reportAuthor: REPORT_AUTHOR,
actionContext: getActionContext(),
externalServerErrorsAsWarning: EXTERNAL_SERVER_ERRORS_AS_WARNINGS,
concurrency: CONCURRENCY ? parseInt(CONCURRENCY, 10) : DEFAULT_CONCURRENCY_LIMIT,
}

if (opts.shouldComment || opts.createReport) {
Expand Down Expand Up @@ -238,6 +270,7 @@ if (import.meta.url.endsWith(process.argv[1])) {
* externalServerErrorsAsWarning {boolean} - Treat >=500 errors or temporary request errors as warning
* filter {Array<string>} - strings to match the pages' relativePath
* versions {Array<string>} - only certain pages' versions (e.g. )
* concurrency {number} - Maximum number of concurrent URL requests (default: 3, env: CONCURRENCY)
*
*/

Expand All @@ -263,6 +296,7 @@ async function main(
reportRepository = 'github/docs-content',
reportAuthor = 'docs-bot',
reportLabel = 'broken link report',
concurrency = DEFAULT_CONCURRENCY_LIMIT,
} = opts

// Note! The reason we're using `warmServer()` in this script,
Expand Down Expand Up @@ -337,8 +371,9 @@ async function main(

debugTimeStart(core, 'processPages')
const t0 = new Date().getTime()
const flawsGroups = await Promise.all(
pages.map((page: Page) =>
const flawsGroups = await limitConcurrency(
pages,
(page: Page) =>
processPage(
core,
page,
Expand All @@ -348,7 +383,7 @@ async function main(
externalLinkCheckerDB,
versions as string[],
),
),
concurrency, // Limit concurrent page checks
)
const t1 = new Date().getTime()
debugTimeEnd(core, 'processPages')
Expand Down Expand Up @@ -653,14 +688,13 @@ async function processPage(
versions: string[],
) {
const { verbose, verboseUrl, bail } = opts
const allFlawsEach = await Promise.all(
page.permalinks
.filter((permalink) => {
return !versions.length || versions.includes(permalink.pageVersion)
})
.map((permalink) => {
return processPermalink(core, permalink, page, pageMap, redirects, opts, db)
}),
const filteredPermalinks = page.permalinks.filter((permalink) => {
return !versions.length || versions.includes(permalink.pageVersion)
})
const allFlawsEach = await limitConcurrency(
filteredPermalinks,
(permalink) => processPermalink(core, permalink, page, pageMap, redirects, opts, db),
opts.concurrency || DEFAULT_CONCURRENCY_LIMIT, // Limit concurrent permalink checks per page
)

const allFlaws = allFlawsEach.flat()
Expand Down Expand Up @@ -714,8 +748,9 @@ async function processPermalink(
$('a[href]').each((i, link) => {
links.push(link)
})
const newFlaws: LinkFlaw[] = await Promise.all(
links.map(async (link) => {
const newFlaws: LinkFlaw[] = await limitConcurrency(
links,
async (link) => {
const { href } = (link as cheerio.TagElement).attribs

// The global cache can't be used for anchor links because they
Expand Down Expand Up @@ -756,7 +791,8 @@ async function processPermalink(
globalHrefCheckCache.set(href, flaw)
}
}
}),
},
opts.concurrency || DEFAULT_CONCURRENCY_LIMIT, // Limit concurrent link checks per permalink
)

for (const flaw of newFlaws) {
Expand Down
Loading