Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Repo sync #35290

Merged
merged 3 commits into from
Nov 14, 2024
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
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
Loading