зеркало из https://github.com/github/docs.git
Коммит
ef684f4d98
|
@ -33,7 +33,7 @@ runs:
|
|||
- name: Run script
|
||||
if: ${{ inputs.restore-only == '' }}
|
||||
shell: bash
|
||||
run: node src/archives/scripts/warmup-remotejson.js
|
||||
run: npm run warmup-remotejson
|
||||
|
||||
- name: Cache .remotejson-cache (save)
|
||||
if: ${{ inputs.restore-only == '' }}
|
||||
|
|
|
@ -7,7 +7,7 @@ name: Purge old workflow runs
|
|||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '20 */2 * * *' # Run every 2 hours at 20 minutes past the hour
|
||||
- cron: '20 * * * *' # Run every hour at 20 minutes past the hour
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
|
|
@ -88,7 +88,7 @@
|
|||
"update-internal-links": "tsx src/links/scripts/update-internal-links.ts",
|
||||
"validate-asset-images": "tsx src/assets/scripts/validate-asset-images.ts",
|
||||
"validate-github-github-docs-urls": "tsx src/links/scripts/validate-github-github-docs-urls/index.ts",
|
||||
"warmup-remotejson": "node src/archives/scripts/warmup-remotejson.js"
|
||||
"warmup-remotejson": "tsx src/archives/scripts/warmup-remotejson.ts"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,mjs,ts,tsx}": "eslint --cache --fix",
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
import type { ExtendedRequest } from '@/types'
|
||||
|
||||
type IsArchivedInfo = {
|
||||
isArchived?: boolean
|
||||
requestedVersion?: string
|
||||
}
|
||||
|
||||
export declare function isArchivedVersion(req: ExtendedRequest): IsArchivedInfo
|
||||
export declare function isArchivedVersionByPath(pathToCheck: string): IsArchivedInfo
|
|
@ -1,14 +1,20 @@
|
|||
import patterns from '#src/frame/lib/patterns.js'
|
||||
import { deprecated } from '#src/versions/lib/enterprise-server-releases.js'
|
||||
import patterns from '@/frame/lib/patterns.js'
|
||||
import { deprecated } from '@/versions/lib/enterprise-server-releases.js'
|
||||
import type { ExtendedRequest } from '@/types'
|
||||
|
||||
export function isArchivedVersion(req) {
|
||||
type IsArchivedInfo = {
|
||||
isArchived?: boolean
|
||||
requestedVersion?: string
|
||||
}
|
||||
|
||||
export function isArchivedVersion(req: ExtendedRequest): IsArchivedInfo {
|
||||
// if this is an assets path, use the referrer
|
||||
// if this is a docs path, use the req.path
|
||||
const pathToCheck = patterns.assetPaths.test(req.path) ? req.get('referrer') : req.path
|
||||
return isArchivedVersionByPath(pathToCheck || '')
|
||||
}
|
||||
|
||||
export function isArchivedVersionByPath(pathToCheck) {
|
||||
export function isArchivedVersionByPath(pathToCheck: string): IsArchivedInfo {
|
||||
// ignore paths that don't have an enterprise version number
|
||||
if (
|
||||
!(
|
||||
|
@ -22,10 +28,10 @@ export function isArchivedVersionByPath(pathToCheck) {
|
|||
// extract enterprise version from path, e.g. 2.16
|
||||
const requestedVersion = pathToCheck.includes('enterprise-server@')
|
||||
? pathToCheck.match(patterns.getEnterpriseServerNumber)?.[1]
|
||||
: pathToCheck.match(patterns.getEnterpriseVersionNumber)[1]
|
||||
: pathToCheck.match(patterns.getEnterpriseVersionNumber)?.[1]
|
||||
|
||||
// bail if the request version is not deprecated
|
||||
if (!deprecated.includes(requestedVersion)) {
|
||||
if (!requestedVersion || !deprecated.includes(requestedVersion)) {
|
||||
return {}
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import path from 'path'
|
||||
import { supported, latest } from '#src/versions/lib/enterprise-server-releases.js'
|
||||
import patterns from '#src/frame/lib/patterns.js'
|
||||
import nonEnterpriseDefaultVersion from '#src/versions/lib/non-enterprise-default-version.js'
|
||||
import { allVersions } from '#src/versions/lib/all-versions.js'
|
||||
import { supported, latest } from '@/versions/lib/enterprise-server-releases.js'
|
||||
import patterns from '@/frame/lib/patterns.js'
|
||||
import nonEnterpriseDefaultVersion from '@/versions/lib/non-enterprise-default-version.js'
|
||||
import { allVersions } from '@/versions/lib/all-versions.js'
|
||||
const latestNewVersion = `enterprise-server@${latest}`
|
||||
const oldVersions = ['dotcom'].concat(supported)
|
||||
const newVersions = Object.keys(allVersions)
|
||||
|
@ -18,7 +18,7 @@ const newVersions = Object.keys(allVersions)
|
|||
// return an old version like 2.21.
|
||||
// Fall back to latest GHES version if one can't be found,
|
||||
// for example, if the new version is private-instances@latest.
|
||||
export function getOldVersionFromNewVersion(newVersion) {
|
||||
export function getOldVersionFromNewVersion(newVersion: string) {
|
||||
return newVersion === nonEnterpriseDefaultVersion
|
||||
? 'dotcom'
|
||||
: oldVersions.find((oldVersion) => newVersion.includes(oldVersion)) || latest
|
||||
|
@ -27,7 +27,7 @@ export function getOldVersionFromNewVersion(newVersion) {
|
|||
// Given an old version like 2.21,
|
||||
// return a new version like enterprise-server@2.21.
|
||||
// Fall back to latest GHES version if one can't be found.
|
||||
export function getNewVersionFromOldVersion(oldVersion) {
|
||||
export function getNewVersionFromOldVersion(oldVersion: string) {
|
||||
return oldVersion === 'dotcom'
|
||||
? nonEnterpriseDefaultVersion
|
||||
: newVersions.find((newVersion) => newVersion.includes(oldVersion)) || latestNewVersion
|
||||
|
@ -35,7 +35,7 @@ export function getNewVersionFromOldVersion(oldVersion) {
|
|||
|
||||
// Given an old path like /enterprise/2.21/user/github/category/article,
|
||||
// return an old version like 2.21.
|
||||
export function getOldVersionFromOldPath(oldPath) {
|
||||
export function getOldVersionFromOldPath(oldPath: string) {
|
||||
// We should never be calling this function on a path that starts with a new version,
|
||||
// so we can assume the path either uses the old /enterprise format or it's dotcom.
|
||||
if (!patterns.enterprise.test(oldPath)) return 'dotcom'
|
||||
|
@ -46,7 +46,7 @@ export function getOldVersionFromOldPath(oldPath) {
|
|||
|
||||
// Given an old path like /en/enterprise/2.21/user/github/category/article,
|
||||
// return a new path like /en/enterprise-server@2.21/github/category/article.
|
||||
export function getNewVersionedPath(oldPath, languageCode = '') {
|
||||
export function getNewVersionedPath(oldPath: string, languageCode = '') {
|
||||
// It's possible a new version has been injected into an old path
|
||||
// via syntax like: /en/enterprise/{{ currentVersion }}/admin/category/article
|
||||
// which could resolve to /en/enterprise/private-instances@latest/admin/category/article,
|
||||
|
@ -58,7 +58,7 @@ export function getNewVersionedPath(oldPath, languageCode = '') {
|
|||
|
||||
// If no new version was found, assume path contains an old version, like 2.21
|
||||
if (!newVersion) {
|
||||
const oldVersion = getOldVersionFromOldPath(oldPath, languageCode)
|
||||
const oldVersion = getOldVersionFromOldPath(oldPath)
|
||||
newVersion = getNewVersionFromOldVersion(oldVersion)
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@ import got from 'got'
|
|||
import type { Response, NextFunction } from 'express'
|
||||
|
||||
import patterns from '@/frame/lib/patterns.js'
|
||||
import { isArchivedVersion } from '@/archives/lib/is-archived-version.js'
|
||||
import { isArchivedVersion } from '@/archives/lib/is-archived-version'
|
||||
import {
|
||||
setFastlySurrogateKey,
|
||||
SURROGATE_ENUMS,
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
} from '@/versions/lib/enterprise-server-releases.js'
|
||||
import patterns from '@/frame/lib/patterns.js'
|
||||
import versionSatisfiesRange from '@/versions/lib/version-satisfies-range.js'
|
||||
import { isArchivedVersion } from '@/archives/lib/is-archived-version.js'
|
||||
import { isArchivedVersion } from '@/archives/lib/is-archived-version'
|
||||
import {
|
||||
setFastlySurrogateKey,
|
||||
SURROGATE_ENUMS,
|
||||
|
|
|
@ -19,12 +19,11 @@
|
|||
// [end-readme]
|
||||
|
||||
import { program } from 'commander'
|
||||
import semver from 'semver'
|
||||
import semver, { SemVer } from 'semver'
|
||||
|
||||
import getRemoteJSON from '#src/frame/lib/get-remote-json.js'
|
||||
import getRemoteJSON from '@/frame/lib/get-remote-json.js'
|
||||
import {
|
||||
deprecated,
|
||||
firstReleaseStoredInBlobStorage,
|
||||
lastVersionWithoutArchivedRedirectsFile,
|
||||
} from '#src/versions/lib/enterprise-server-releases.js'
|
||||
|
||||
|
@ -36,18 +35,14 @@ program
|
|||
|
||||
main()
|
||||
|
||||
function version2url(version) {
|
||||
const inBlobStorage = semver.gte(
|
||||
semver.coerce(version).raw,
|
||||
semver.coerce(firstReleaseStoredInBlobStorage).raw,
|
||||
)
|
||||
function version2url(version: string | SemVer) {
|
||||
return `https://github.github.com/docs-ghes-${version}/redirects.json`
|
||||
}
|
||||
|
||||
function withArchivedRedirectsFile(version) {
|
||||
function withArchivedRedirectsFile(version: string | SemVer) {
|
||||
return semver.eq(
|
||||
semver.coerce(version).raw,
|
||||
semver.coerce(lastVersionWithoutArchivedRedirectsFile).raw,
|
||||
semver.coerce(version)?.raw || '',
|
||||
semver.coerce(lastVersionWithoutArchivedRedirectsFile)?.raw || '',
|
||||
)
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import { describe, expect, test, vi } from 'vitest'
|
||||
|
||||
import enterpriseServerReleases from '#src/versions/lib/enterprise-server-releases.js'
|
||||
import { get, getDOM } from '#src/tests/helpers/e2etest.js'
|
||||
import { SURROGATE_ENUMS } from '#src/frame/middleware/set-fastly-surrogate-key.js'
|
||||
import enterpriseServerReleases from '@/versions/lib/enterprise-server-releases.js'
|
||||
import { get, getDOM } from '@/tests/helpers/e2etest-ts'
|
||||
import { SURROGATE_ENUMS } from '@/frame/middleware/set-fastly-surrogate-key.js'
|
||||
|
||||
describe('enterprise deprecation', () => {
|
||||
vi.setConfig({ testTimeout: 60 * 1000 })
|
||||
|
@ -45,8 +45,8 @@ describe('enterprise deprecation', () => {
|
|||
|
||||
test('handles requests for deprecated Enterprise pages ( >=2.13 )', async () => {
|
||||
expect(enterpriseServerReleases.deprecated.includes('2.13')).toBe(true)
|
||||
const $ = await getDOM('/en/enterprise/2.13/user/articles/about-branches')
|
||||
expect($.res.statusCode).toBe(200)
|
||||
const { $, res } = await getDOM('/en/enterprise/2.13/user/articles/about-branches')
|
||||
expect(res.statusCode).toBe(200)
|
||||
expect($('h1').first().text()).toBe('About branches')
|
||||
})
|
||||
|
||||
|
@ -60,27 +60,27 @@ describe('enterprise deprecation', () => {
|
|||
|
||||
test('handles requests for deprecated Enterprise pages ( <2.13 )', async () => {
|
||||
expect(enterpriseServerReleases.deprecated.includes('2.12')).toBe(true)
|
||||
const $ = await getDOM('/enterprise/2.12/user/articles/about-branches')
|
||||
expect($.res.statusCode).toBe(200)
|
||||
const { $, res } = await getDOM('/enterprise/2.12/user/articles/about-branches')
|
||||
expect(res.statusCode).toBe(200)
|
||||
expect($('h2').text()).toBe('About branches')
|
||||
})
|
||||
|
||||
test('handles requests for deprecated Enterprise version 11.10.340', async () => {
|
||||
expect(enterpriseServerReleases.deprecated.includes('11.10.340')).toBe(true)
|
||||
const $ = await getDOM('/enterprise/11.10.340/admin/articles/adding-teams')
|
||||
expect($.res.statusCode).toBe(200)
|
||||
const { $, res } = await getDOM('/enterprise/11.10.340/admin/articles/adding-teams')
|
||||
expect(res.statusCode).toBe(200)
|
||||
expect($('h2').text()).toBe('Adding teams')
|
||||
})
|
||||
|
||||
test('has working admin guide links ( <2.13 )', async () => {
|
||||
const guidesPath = '/enterprise/2.12/admin'
|
||||
let $ = await getDOM(`${guidesPath}/guides`)
|
||||
const firstLink = $('[class="guide-section"]').children('a').attr('href')
|
||||
const { $: $1 } = await getDOM(`${guidesPath}/guides`)
|
||||
const firstLink = $1('[class="guide-section"]').children('a').attr('href')
|
||||
|
||||
$ = await getDOM(`${guidesPath}/${firstLink}`)
|
||||
expect($.res.statusCode).toBe(200)
|
||||
const { $: $2, res } = await getDOM(`${guidesPath}/${firstLink}`)
|
||||
expect(res.statusCode).toBe(200)
|
||||
// this test assumes the Installation guide is the first link on the guides page
|
||||
expect($('h2').text()).toBe('Installing and configuring GitHub Enterprise')
|
||||
expect($2('h2').text()).toBe('Installing and configuring GitHub Enterprise')
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -139,22 +139,22 @@ describe('recently deprecated redirects', () => {
|
|||
|
||||
describe('deprecation banner', () => {
|
||||
test('renders a deprecation warning banner on oldest supported Enterprise version', async () => {
|
||||
const $ = await getDOM(`/en/enterprise/${enterpriseServerReleases.oldestSupported}`)
|
||||
const { $ } = await getDOM(`/en/enterprise/${enterpriseServerReleases.oldestSupported}`)
|
||||
expect($('[data-testid=deprecation-banner]').length).toBe(1)
|
||||
})
|
||||
|
||||
test('does not render a deprecation warning banner on other Enterprise versions', async () => {
|
||||
const $ = await getDOM(`/en/enterprise/${enterpriseServerReleases.latest}`)
|
||||
const { $ } = await getDOM(`/en/enterprise/${enterpriseServerReleases.latest}`)
|
||||
expect($('[data-testid=deprecation-banner]').length).toBe(0)
|
||||
})
|
||||
|
||||
test('deprecation warning banner includes a date', async () => {
|
||||
const $ = await getDOM(`/en/enterprise/${enterpriseServerReleases.oldestSupported}`)
|
||||
const { $ } = await getDOM(`/en/enterprise/${enterpriseServerReleases.oldestSupported}`)
|
||||
expect($('[data-testid=deprecation-banner] b').text().endsWith('discontinued on .')).toBe(false)
|
||||
})
|
||||
|
||||
test('deprecation warning banner includes the right text depending on the date', async () => {
|
||||
const $ = await getDOM(`/en/enterprise/${enterpriseServerReleases.oldestSupported}`)
|
||||
const { $ } = await getDOM(`/en/enterprise/${enterpriseServerReleases.oldestSupported}`)
|
||||
const expectedString = enterpriseServerReleases.isOldestReleaseDeprecated
|
||||
? 'was discontinued'
|
||||
: 'will be discontinued'
|
||||
|
@ -164,24 +164,28 @@ describe('deprecation banner', () => {
|
|||
|
||||
describe('does not render survey prompt or contribution button', () => {
|
||||
test('does not render survey prompt', async () => {
|
||||
let $ = await getDOM(`/en/enterprise/${enterpriseServerReleases.latest}/github`)
|
||||
expect($('[data-testid="survey-form"]').length).toBeGreaterThan(0)
|
||||
$ = await getDOM(`/en/enterprise/${enterpriseServerReleases.oldestSupported}/github`)
|
||||
const { $: $1 } = await getDOM(`/en/enterprise/${enterpriseServerReleases.latest}/github`)
|
||||
expect($1('[data-testid="survey-form"]').length).toBeGreaterThan(0)
|
||||
const { $: $2 } = await getDOM(
|
||||
`/en/enterprise/${enterpriseServerReleases.oldestSupported}/github`,
|
||||
)
|
||||
if (enterpriseServerReleases.isOldestReleaseDeprecated) {
|
||||
expect($('[data-testid="survey-form"]').length).toBe(0)
|
||||
expect($2('[data-testid="survey-form"]').length).toBe(0)
|
||||
} else {
|
||||
expect($('[data-testid="survey-form"]').length).toBeGreaterThan(0)
|
||||
expect($2('[data-testid="survey-form"]').length).toBeGreaterThan(0)
|
||||
}
|
||||
})
|
||||
|
||||
test('does not render contribution button', async () => {
|
||||
let $ = await getDOM(`/en/enterprise/${enterpriseServerReleases.latest}/github`)
|
||||
expect($('.contribution').length).toBeGreaterThan(0)
|
||||
$ = await getDOM(`/en/enterprise/${enterpriseServerReleases.oldestSupported}/github`)
|
||||
const { $: $1 } = await getDOM(`/en/enterprise/${enterpriseServerReleases.latest}/github`)
|
||||
expect($1('.contribution').length).toBeGreaterThan(0)
|
||||
const { $: $2 } = await getDOM(
|
||||
`/en/enterprise/${enterpriseServerReleases.oldestSupported}/github`,
|
||||
)
|
||||
if (enterpriseServerReleases.isOldestReleaseDeprecated) {
|
||||
expect($('.contribution').length).toBe(0)
|
||||
expect($2('.contribution').length).toBe(0)
|
||||
} else {
|
||||
expect($('[data-testid=survey-form]').length).toBeGreaterThan(0)
|
||||
expect($2('[data-testid=survey-form]').length).toBeGreaterThan(0)
|
||||
}
|
||||
})
|
||||
})
|
|
@ -5,7 +5,7 @@ import stripAnsi from 'strip-ansi'
|
|||
import { visit } from 'unist-util-visit'
|
||||
import { distance } from 'fastest-levenshtein'
|
||||
import { getPathWithoutLanguage, getVersionStringFromPath } from '#src/frame/lib/path-utils.js'
|
||||
import { getNewVersionedPath } from '#src/archives/lib/old-versions-utils.js'
|
||||
import { getNewVersionedPath } from '#src/archives/lib/old-versions-utils.ts'
|
||||
import patterns from '#src/frame/lib/patterns.js'
|
||||
import { deprecated, latest } from '#src/versions/lib/enterprise-server-releases.js'
|
||||
import nonEnterpriseDefaultVersion from '#src/versions/lib/non-enterprise-default-version.js'
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import type { NextFunction, Request, Response } from 'express'
|
||||
import helmet from 'helmet'
|
||||
import { isArchivedVersion } from '@/archives/lib/is-archived-version.js'
|
||||
import { isArchivedVersion } from '@/archives/lib/is-archived-version'
|
||||
import versionSatisfiesRange from '@/versions/lib/version-satisfies-range.js'
|
||||
import { languagePrefixPathRegex } from '@/languages/lib/languages.js'
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ import shortVersions from '@/versions/middleware/short-versions.js'
|
|||
import contextualize from '@/frame/middleware/context/context'
|
||||
import features from '@/versions/middleware/features.js'
|
||||
import getRedirect from '@/redirects/lib/get-redirect.js'
|
||||
import { isArchivedVersionByPath } from '@/archives/lib/is-archived-version.js'
|
||||
import { isArchivedVersionByPath } from '@/archives/lib/is-archived-version'
|
||||
import { readCompressedJsonFile } from '@/frame/lib/read-json-file.js'
|
||||
|
||||
const router = express.Router()
|
||||
|
|
|
@ -32,7 +32,7 @@ describeIfElasticsearchURL('search rendering page', () => {
|
|||
// To see why this will work,
|
||||
// see src/search/tests/fixtures/search-indexes/github-docs-dotcom-en-records.json
|
||||
// which clearly has a record with the title "Foo"
|
||||
const $ = await getDOM('/en/search?query=foo')
|
||||
const { $ } = await getDOM('/en/search?query=foo')
|
||||
expect($('h1').text()).toMatch(/\d+ Search results for "foo"/)
|
||||
|
||||
// Note it testid being 'search-result', not 'search-results'
|
||||
|
@ -62,7 +62,7 @@ describeIfElasticsearchURL('search rendering page', () => {
|
|||
})
|
||||
|
||||
test('debug search', async () => {
|
||||
const $ = await getDOM('/en/search?query=foo&debug=1')
|
||||
const { $ } = await getDOM('/en/search?query=foo&debug=1')
|
||||
expect($('h1').text()).toMatch(/\d+ Search results for "foo"/)
|
||||
|
||||
// Note it testid being 'search-result', not 'search-results'
|
||||
|
@ -74,21 +74,21 @@ describeIfElasticsearchURL('search rendering page', () => {
|
|||
})
|
||||
|
||||
test('no query', async () => {
|
||||
const $ = await getDOM('/en/search')
|
||||
const { $ } = await getDOM('/en/search')
|
||||
const results = $('[data-testid="search-result"]')
|
||||
expect(results.length).toBe(0)
|
||||
expect($('[data-testid="search-results"]').text()).toMatch('Enter a search term')
|
||||
})
|
||||
|
||||
test('empty query', async () => {
|
||||
const $ = await getDOM('/en/search?query=')
|
||||
const { $ } = await getDOM('/en/search?query=')
|
||||
const results = $('[data-testid="search-result"]')
|
||||
expect(results.length).toBe(0)
|
||||
expect($('[data-testid="search-results"]').text()).toMatch('Enter a search term')
|
||||
})
|
||||
|
||||
test('find nothing', async () => {
|
||||
const $ = await getDOM('/en/search?query=xojixjoiwejhfoiuwehjfioweufhj')
|
||||
const { $ } = await getDOM('/en/search?query=xojixjoiwejhfoiuwehjfioweufhj')
|
||||
const results = $('[data-testid="search-result"]')
|
||||
expect(results.length).toBe(0)
|
||||
expect($('[data-testid="search-results"]').text()).toMatch('0 Search results')
|
||||
|
@ -100,7 +100,7 @@ describeIfElasticsearchURL('search rendering page', () => {
|
|||
})
|
||||
|
||||
test('links per version in pathname', async () => {
|
||||
const $ = await getDOM('/en/enterprise-cloud@latest/search?query=foo')
|
||||
const { $ } = await getDOM('/en/enterprise-cloud@latest/search?query=foo')
|
||||
expect($('[data-testid="search-results"]').text()).toMatch('Exclusively for GHEC')
|
||||
// Note it testid being 'search-result', not 'search-results'
|
||||
const results = $('[data-testid="search-result"]')
|
||||
|
@ -115,14 +115,14 @@ describeIfElasticsearchURL('search rendering page', () => {
|
|||
})
|
||||
|
||||
test('invalid parameters (page)', async () => {
|
||||
const $ = await getDOM('/en/search?query=foo&page=999')
|
||||
const { $ } = await getDOM('/en/search?query=foo&page=999')
|
||||
expect($('[data-testid="search-results"]').text()).toMatch('Not a valid value (999)')
|
||||
const results = $('[data-testid="search-result"]')
|
||||
expect(results.length).toBe(0)
|
||||
})
|
||||
|
||||
test('invalid parameters (size)', async () => {
|
||||
const $ = await getDOM('/en/search?query=foo&size=888')
|
||||
const { $ } = await getDOM('/en/search?query=foo&size=888')
|
||||
expect($('[data-testid="search-results"]').text()).toMatch('Not a valid value (888)')
|
||||
const results = $('[data-testid="search-result"]')
|
||||
expect(results.length).toBe(0)
|
||||
|
@ -134,14 +134,14 @@ describeIfElasticsearchURL('search rendering page', () => {
|
|||
})
|
||||
|
||||
test('more than one search query', async () => {
|
||||
const $ = await getDOM('/en/search?query=foo&query=bar')
|
||||
const { $ } = await getDOM('/en/search?query=foo&query=bar')
|
||||
expect($('[data-testid="search-results"]').text()).toMatch('Cannot have multiple values')
|
||||
const results = $('[data-testid="search-result"]')
|
||||
expect(results.length).toBe(0)
|
||||
})
|
||||
|
||||
test("search with 'toplevel' query string", async () => {
|
||||
const $ = await getDOM('/en/search?query=foo&toplevel=Baring')
|
||||
const { $ } = await getDOM('/en/search?query=foo&toplevel=Baring')
|
||||
expect($('h1').text()).toMatch(/\d+ Search results for "foo"/)
|
||||
|
||||
// Note it testid being 'search-result', not 'search-results'
|
||||
|
|
|
@ -5,7 +5,7 @@ describe('search results page', () => {
|
|||
vi.setConfig({ testTimeout: 60 * 1000 })
|
||||
|
||||
test('says something if no query is provided', async (): Promise<void> => {
|
||||
const $ = await getDOM('/en/search')
|
||||
const { $ } = await getDOM('/en/search')
|
||||
const $container = $('[data-testid="search-results"]')
|
||||
expect($container.text()).toMatch(/Enter a search term/)
|
||||
// Default is the frontmatter title of the content/search/index.md
|
||||
|
@ -14,7 +14,7 @@ describe('search results page', () => {
|
|||
|
||||
test('says something if query is empty', async (): Promise<void> => {
|
||||
const queryParams = new URLSearchParams({ query: ' ' }).toString()
|
||||
const $ = await getDOM(`/en/search?${queryParams}`)
|
||||
const { $ } = await getDOM(`/en/search?${queryParams}`)
|
||||
const $container = $('[data-testid="search-results"]')
|
||||
expect($container.text()).toMatch(/Enter a search term/)
|
||||
})
|
||||
|
@ -22,7 +22,7 @@ describe('search results page', () => {
|
|||
test('mentions search term in h1', async (): Promise<void> => {
|
||||
const searchTerm = 'peterbe'
|
||||
const queryParams = new URLSearchParams({ query: searchTerm }).toString()
|
||||
const $ = await getDOM(`/en/search?${queryParams}`)
|
||||
const { $ } = await getDOM(`/en/search?${queryParams}`)
|
||||
const $container = $('[data-testid="search-results"]')
|
||||
const h1Text: string = $container.find('h1').text()
|
||||
|
||||
|
|
|
@ -122,8 +122,8 @@ export async function getDOMCached(
|
|||
): Promise<cheerio.Root> {
|
||||
const key = `${route}::${JSON.stringify(options)}`
|
||||
if (!getDOMCache.has(key)) {
|
||||
const dom = await getDOM(route, options)
|
||||
getDOMCache.set(key, dom)
|
||||
const { $ } = await getDOM(route, options)
|
||||
getDOMCache.set(key, $)
|
||||
}
|
||||
// The non-null assertion is safe here because we've just set the key if it didn't exist
|
||||
return getDOMCache.get(key)!
|
||||
|
@ -136,7 +136,10 @@ export async function getDOMCached(
|
|||
* @param options - Options for fetching the DOM.
|
||||
* @returns A promise that resolves to the loaded DOM object.
|
||||
*/
|
||||
export async function getDOM(route: string, options: GetDOMOptions = {}): Promise<cheerio.Root> {
|
||||
export async function getDOM(
|
||||
route: string,
|
||||
options: GetDOMOptions = {},
|
||||
): Promise<{ $: cheerio.Root; res: Response }> {
|
||||
const { headers, allow500s = false, allow404 = false, retries = 0 } = options
|
||||
const res = await get(route, { followRedirects: true, headers, retries })
|
||||
|
||||
|
@ -150,10 +153,7 @@ export async function getDOM(route: string, options: GetDOMOptions = {}): Promis
|
|||
|
||||
const $ = cheerio.load(res.body || '', { xmlMode: true })
|
||||
|
||||
// Extend the Cheerio instance with the response object
|
||||
;($ as any).res = { ...res }
|
||||
|
||||
return $
|
||||
return { $, res }
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* For every run found, it deletes its logs and its run.
|
||||
*
|
||||
* The total number of deletions is limited by the `MAX_DELETIONS`
|
||||
* environment variable. The default is 100.
|
||||
* environment variable. The default is 2000.
|
||||
* */
|
||||
|
||||
import fs from 'fs'
|
||||
|
@ -29,7 +29,7 @@ import { getOctokit } from '@actions/github'
|
|||
main()
|
||||
async function main() {
|
||||
const DRY_RUN = Boolean(JSON.parse(process.env.DRY_RUN || 'false'))
|
||||
const MAX_DELETIONS = parseInt(JSON.parse(process.env.MAX_DELETIONS || '100'))
|
||||
const MAX_DELETIONS = parseInt(JSON.parse(process.env.MAX_DELETIONS || '2000'))
|
||||
const MIN_AGE_DAYS = parseInt(process.env.MIN_AGE_DAYS || '90', 10)
|
||||
|
||||
const [owner, repo] = process.env.GITHUB_REPOSITORY.split('/')
|
||||
|
@ -134,11 +134,11 @@ async function deleteWorkflowRuns(
|
|||
owner,
|
||||
repo,
|
||||
workflow,
|
||||
{ dryRun = false, minAgeDays = 100, maxDeletions = 1000 },
|
||||
{ dryRun = false, minAgeDays = 90, maxDeletions = 2000 },
|
||||
) {
|
||||
// https://docs.github.com/en/search-github/getting-started-with-searching-on-github/understanding-the-search-syntax#query-for-dates
|
||||
const minCreated = new Date(Date.now() - minAgeDays * 24 * 60 * 60 * 1000)
|
||||
const minCreatedSearch = `<=${minCreated.toISOString().split('T')[0]}`
|
||||
const minCreatedSearch = `<${minCreated.toISOString().split('T')[0]}`
|
||||
// Delete is 10, but max is 100. But if we're only going to delete,
|
||||
// 30, use 30. And if we're only going to delete 5, use the default
|
||||
// per_page value of 10.
|
||||
|
|
Загрузка…
Ссылка в новой задаче