Skip to content

Commit

Permalink
Merge pull request github#35290 from github/repo-sync
Browse files Browse the repository at this point in the history
Repo sync
  • Loading branch information
docs-bot authored Nov 14, 2024
2 parents 77eebab + ff3bd58 commit a3596d1
Show file tree
Hide file tree
Showing 21 changed files with 571 additions and 71 deletions.
7 changes: 6 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,9 @@ BUILD_RECORDS_MAX_CONCURRENT=100
BUILD_RECORDS_MIN_TIME=

# Set to true to enable the /fastly-cache-test route for debugging Fastly headers
ENABLE_FASTLY_TESTING=
ENABLE_FASTLY_TESTING=

# Needed to auth for AI search
CSE_COPILOT_SECRET=
CSE_COPILOT_ENDPOINT=https://cse-copilot-staging.service.iad.github.net

Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ on:
- 'content/contributing/**.md'

jobs:
codeowners-content-strategy:
codeowners-content-systems:
if: ${{ github.repository == 'github/docs-internal' }}
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1

- name: Add Content Strategy as a reviewer
- name: Add Content Systems as a reviewer
env:
GH_TOKEN: ${{ secrets.DOCS_BOT_PAT_WRITEORG_PROJECT }}
PR: ${{ github.event.pull_request.html_url }}
Expand All @@ -29,5 +29,5 @@ jobs:
)
if ! $has_reviewer
then
gh pr edit $PR --add-reviewer github/docs-content-strategy
gh pr edit $PR --add-reviewer github/docs-content-systems
fi
38 changes: 21 additions & 17 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"delete-orphan-translation-files": "tsx src/workflows/delete-orphan-translation-files.ts",
"deleted-features-pr-comment": "tsx src/data-directory/scripts/deleted-features-pr-comment.ts",
"dev": "cross-env npm start",
"find-orphaned-assets": "node src/assets/scripts/find-orphaned-assets.js",
"find-orphaned-assets": "tsx src/assets/scripts/find-orphaned-assets.ts",
"find-orphaned-features": "tsx src/data-directory/scripts/find-orphaned-features/index.ts",
"find-past-built-pr": "tsx src/workflows/find-past-built-pr.ts",
"find-unused-variables": "tsx src/content-linter/scripts/find-unsed-variables.ts",
Expand Down Expand Up @@ -259,7 +259,7 @@
"express": "4.21.1",
"express-rate-limit": "7.4.0",
"fastest-levenshtein": "1.0.16",
"file-type": "19.4.1",
"file-type": "19.6.0",
"flat": "^6.0.1",
"github-slugger": "^2.0.0",
"glob": "11.0.0",
Expand Down
1 change: 1 addition & 0 deletions src/assets/lib/image-density.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const IMAGE_DENSITY: Record<string, string>
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,19 @@
// [end-readme]

import { program } from 'commander'
import main from './deleted-assets-pr-comment.js'
import main from './deleted-assets-pr-comment'

program
.description('If applicable, print a snippet of Markdown about deleted assets')
.arguments('owner repo base_sha head_sha', 'Simulate what the Actions workflow does')
.arguments('owner repo base_sha head_sha')
.parse(process.argv)

const opts = program.opts()
const args = program.args
type MainArgs = {
owner: string
repo: string
baseSHA: string
headSHA: string
}
const opts = program.opts() as MainArgs

console.log(await main(...args, { ...opts }))
console.log(await main(opts))
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,22 @@ if (!GITHUB_TOKEN) {
// When this file is invoked directly from action as opposed to being imported
if (import.meta.url.endsWith(process.argv[1])) {
const owner = context.repo.owner
const repo = context.payload.repository.name
const baseSHA = context.payload.pull_request.base.sha
const headSHA = context.payload.pull_request.head.sha
const repo = context.payload.repository?.name || ''
const baseSHA = context.payload.pull_request?.base.sha
const headSHA = context.payload.pull_request?.head.sha

const markdown = await main(owner, repo, baseSHA, headSHA)
const markdown = await main({ owner, repo, baseSHA, headSHA })
core.setOutput('markdown', markdown)
}

async function main(owner, repo, baseSHA, headSHA) {
const octokit = github.getOctokit(GITHUB_TOKEN)
type MainArgs = {
owner: string
repo: string
baseSHA: string
headSHA: string
}
async function main({ owner, repo, baseSHA, headSHA }: MainArgs) {
const octokit = github.getOctokit(GITHUB_TOKEN as string)
// get the list of file changes from the PR
const response = await octokit.rest.repos.compareCommitsWithBasehead({
owner,
Expand All @@ -32,6 +38,10 @@ async function main(owner, repo, baseSHA, headSHA) {

const { files } = response.data

if (!files) {
throw new Error('No files found in the PR')
}

const oldFilenames = []
for (const file of files) {
const { filename, status } = file
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const EXCEPTIONS = new Set([
'assets/images/site/apple-touch-icon-76x76.png',
])

function isExceptionPath(imagePath) {
function isExceptionPath(imagePath: string) {
// We also check for .DS_Store because any macOS user that has opened
// a folder with images will have this on disk. It won't get added
// to git anyway thanks to our .DS_Store.
Expand All @@ -53,9 +53,15 @@ program
.option('--exclude-translations', "Don't search in translations/")
.parse(process.argv)

main(program.opts(), program.args)
type MainOptions = {
json: boolean
verbose: boolean
exit: boolean
excludeTranslations: boolean
}
main(program.opts())

async function main(opts) {
async function main(opts: MainOptions) {
const { json, verbose, exit, excludeTranslations } = opts

const walkOptions = {
Expand Down Expand Up @@ -164,7 +170,7 @@ async function main(opts) {
}
}

function getTotalDiskSize(filePaths) {
function getTotalDiskSize(filePaths: Set<string>) {
let sum = 0
for (const filePath of filePaths) {
sum += fs.statSync(filePath).size
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,26 @@ import { fileURLToPath } from 'url'
import path from 'path'
import walk from 'walk-sync'
import sharp from 'sharp'
import { chain } from 'lodash-es'
const __dirname = path.dirname(fileURLToPath(import.meta.url))

const imagesPath = path.join(__dirname, '../assets/images')
const imagesExtensions = ['.jpg', '.jpeg', '.png', '.gif']

const files = chain(walk(imagesPath, { directories: false })).filter((relativePath) => {
const files = walk(imagesPath, { directories: false }).filter((relativePath) => {
return imagesExtensions.includes(path.extname(relativePath.toLowerCase()))
})
const infos = await Promise.all(
const images = await Promise.all(
files.map(async (relativePath) => {
const fullPath = path.join(imagesPath, relativePath)
const image = sharp(fullPath)
const { width, height } = await image.metadata()
const size = width * height
const size = (width || 0) * (height || 0)
return { relativePath, width, height, size }
}),
)
const images = files
.map((relativePath, i) => {
return { relativePath, ...infos[i] }
images
.sort((a, b) => b.size - a.size)
.forEach((image) => {
const { relativePath, width, height } = image
console.log(`${width} x ${height} - ${relativePath}`)
})
.orderBy('size', 'desc')
.value()

images.forEach((image) => {
const { relativePath, width, height } = image
console.log(`${width} x ${height} - ${relativePath}`)
})
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import path from 'path'
import { program } from 'commander'
import chalk from 'chalk'
import cheerio from 'cheerio'
// @ts-ignore see https://github.com/sindresorhus/file-type/issues/652
import { fileTypeFromFile } from 'file-type'
import walk from 'walk-sync'
import isSVG from 'is-svg'
Expand All @@ -43,7 +44,7 @@ const EXPECT = {
'.ico': 'image/x-icon',
'.pdf': 'application/pdf',
'.webp': 'image/webp',
}
} as Record<string, string>

const CRITICAL = 'critical'
const WARNING = 'warning'
Expand All @@ -56,7 +57,7 @@ program

main(program.opts())

async function main(opts) {
async function main(opts: { dryRun: boolean; verbose: boolean }) {
let errors = 0

const files = walk(ASSETS_ROOT, { includeBasePath: true, directories: false }).filter(
Expand All @@ -71,7 +72,11 @@ async function main(opts) {
)
},
)
const results = (await Promise.all(files.map(checkFile))).filter(Boolean)
const results = (await Promise.all(files.map(checkFile))).filter(Boolean) as [
level: string,
filePath: string,
error: string,
][]
for (const [level, filePath, error] of results) {
console.log(
level === CRITICAL ? chalk.red(level) : chalk.yellow(level),
Expand All @@ -94,7 +99,7 @@ async function main(opts) {
process.exitCode = errors
}

async function checkFile(filePath) {
async function checkFile(filePath: string) {
const ext = path.extname(filePath)

const { size } = await fs.stat(filePath)
Expand All @@ -113,7 +118,7 @@ async function checkFile(filePath) {
}
try {
checkSVGContent(content)
} catch (error) {
} catch (error: any) {
return [CRITICAL, filePath, error.message]
}
} else if (EXPECT[ext]) {
Expand All @@ -135,15 +140,15 @@ async function checkFile(filePath) {
// All is well. Nothing to complain about.
}

function checkSVGContent(content) {
function checkSVGContent(content: string) {
const $ = cheerio.load(content)
const disallowedTagNames = new Set(['script', 'object', 'iframe', 'embed'])
$('*').each((i, element) => {
const { tagName } = element
const { tagName } = $(element).get(0)
if (disallowedTagNames.has(tagName)) {
throw new Error(`contains a <${tagName}> tag`)
}
for (const key in element.attribs) {
for (const key in $(element).get(0).attribs) {
// Looks for suspicious event handlers on tags.
// For example `<path oNload="alert(1)"" d="M28 0l4.59 4.59-9.76`
// We don't need to do a case-sensitive regex here because cheerio
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { describe, expect, test, vi } from 'vitest'
import { get } from '#src/tests/helpers/e2etest.js'
import { checkCachingHeaders } from '#src/tests/helpers/caching-headers.js'

function getNextStaticAsset(directory) {
function getNextStaticAsset(directory: string) {
const root = path.join('.next', 'static', directory)
const files = fs.readdirSync(root)
if (!files.length) throw new Error(`Can't find any files in ${root}`)
Expand Down
18 changes: 18 additions & 0 deletions src/frame/middleware/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { createProxyMiddleware } from 'http-proxy-middleware'

import events from '@/events/middleware.js'
import anchorRedirect from '@/rest/api/anchor-redirect.js'
import aiSearch from '@/search/middleware/ai-search'
import search from '@/search/middleware/search-routes.js'
import pageInfo from '@/pageinfo/middleware'
import pageList from '@/pagelist/middleware'
Expand All @@ -23,6 +24,23 @@ router.use('/pagelist', pageList)
// local laptop, they don't have an Elasticsearch. Neither a running local
// server or the known credentials to a remote Elasticsearch. Whenever
// that's the case, they can just HTTP proxy to the production server.
if (process.env.CSE_COPILOT_ENDPOINT || process.env.NODE_ENV === 'test') {
router.use('/ai-search', aiSearch)
} else {
console.log(
'Proxying AI Search requests to docs.github.com. To use the cse-copilot endpoint, set the CSE_COPILOT_ENDPOINT environment variable.',
)
router.use(
'/ai-search',
createProxyMiddleware({
target: 'https://docs.github.com',
changeOrigin: true,
pathRewrite: function (path, req: ExtendedRequest) {
return req.originalUrl
},
}),
)
}
if (process.env.ELASTICSEARCH_URL) {
router.use('/search', search)
} else {
Expand Down
Loading

0 comments on commit a3596d1

Please sign in to comment.