From 613b6a252d384d88a1dd21c1f6df88cdb878f742 Mon Sep 17 00:00:00 2001 From: Adam Gordon Bell <v-adam@pulumi.com> Date: Tue, 4 Feb 2025 09:54:17 -0500 Subject: [PATCH] Get CI working Update `@types/ms` resolution to version 0.7.32 in `package.json` and `yarn.lock`. Add ts-node script and update linting commands in package.json and lint.sh. Enhance CI workflow with debug info for PR events; add new blog post template and assets. Refactor types in find-markdown.ts and add test PR event JSON file. Refactor PR file handling: update to use 'files' instead of 'added_files' for added file tracking in GitHub Actions. Adjust test data accordingly. Remove debug logging and add base branch environment variable in workflows Enhance GitHub Actions workflow: add branch info echo and ensure make step before linting. Refactor linting scripts and update pull request workflow - Removed lint step from GitHub Actions workflow - Simplified the `find-markdown.ts` script by removing GHA-related functionality - Updated `getGitModifiedFiles` to accept a base branch parameter - Resolved types and streamlined logic for markdown file detection - Adjusted lint scripts to handle modes more effectively Update markdown linting script to exclude 'node_modules' directory and add debug logging functionality in the linting process. Set DEBUG mode to off by default. Update GitHub Actions workflow and improve file detection logic - Upgraded `actions/checkout` from v2 to v4 and set fetch depth. - Enhanced `getGitModifiedFiles` function to handle both local and GitHub Actions environments. - Improved error handling and added debug logging for file detection. Refactor GitHub Actions workflow and TypeScript script for enhanced efficiency and clarity in fetching branches and modified files. --- .github/workflows/pull-request.yml | 30 ++++++- content/blog/sfsdfsfs/index.md | 85 ++++++++++++++++++ content/blog/sfsdfsfs/meta.png | Bin 0 -> 24665 bytes package.json | 6 +- scripts/lint/find-markdown.ts | 130 +++++++++++++++++++-------- scripts/lint/lint.sh | 24 +++-- scripts/lint/markdownlint-runner.ts | 4 +- scripts/lint/test-pr-event.json | 32 +++++++ scripts/lint/validate-frontmatter.ts | 4 +- yarn.lock | 8 +- 10 files changed, 268 insertions(+), 55 deletions(-) create mode 100644 content/blog/sfsdfsfs/index.md create mode 100644 content/blog/sfsdfsfs/meta.png create mode 100644 scripts/lint/test-pr-event.json diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index a4dfdbfb91575..24b0cf257d1ee 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -19,12 +19,35 @@ jobs: environment: testing steps: - - uses: actions/checkout@v2 - + - uses: actions/checkout@v4 + with: + # Only fetch PR branch + fetch-depth: 1 + ref: ${{ github.event.pull_request.head.sha }} + + - name: Fetch base branch + run: | + # Fetch and create local master branch + git -c protocol.version=2 fetch --no-tags --prune --progress --no-recurse-submodules --depth=1 origin master:master + # Verify branches + echo "Local branches:" + git branch -v + echo "\nRemote branches:" + git branch -r + + - name: Set base branch env + run: | + if [ "${{ github.event_name }}" = "pull_request" ]; then + echo "BASE_BRANCH=${{ github.event.pull_request.base.ref }}" >> $GITHUB_ENV + else + # This covers push scenario to master + # or any other scenario with no PR info + echo "BASE_BRANCH=" >> $GITHUB_ENV + fi + echo "Branch:${{ github.event.pull_request.base.ref }}" - uses: actions/setup-node@v1 with: node-version: '18.x' - - uses: peaceiris/actions-hugo@v2 with: hugo-version: '0.135.0' @@ -55,6 +78,7 @@ jobs: ALGOLIA_APP_SEARCH_KEY: ${{ vars.ALGOLIA_APP_SEARCH_KEY }} ALGOLIA_APP_ADMIN_KEY: ${{ secrets.ALGOLIA_APP_ADMIN_KEY }} NODE_OPTIONS: "--max_old_space_size=8192" + BASE_BRANCH: ${{ env.BASE_BRANCH }} - name: Archive test results uses: actions/upload-artifact@v4 diff --git a/content/blog/sfsdfsfs/index.md b/content/blog/sfsdfsfs/index.md new file mode 100644 index 0000000000000..73fc26fd78343 --- /dev/null +++ b/content/blog/sfsdfsfs/index.md @@ -0,0 +1,85 @@ +--- +title: "Sfsdfsfs" + +# The date represents the post's publish date, and by default corresponds with +# the date and time this file was generated. Dates are used for display and +# ordering purposes only; they have no effect on whether or when a post is +# published. To influence the ordering of posts published on the same date, use +# the time portion of the date value; posts are sorted in descending order by +# date/time. +date: 2025-02-04T10:14:44-05:00 + +# The draft setting determines whether a post is published. Set it to true if +# you want to be able to merge the post without publishing it. +draft: false + +# Use the meta_desc property to provide a brief summary (one or two sentences) +# of the content of the post, which is useful for targeting search results or +# social-media previews. This field is required or the build will fail the +# linter test. Max length is 160 characters. +meta_desc: + +# The meta_image appears in social-media previews and on the blog home page. A +# placeholder image representing the recommended format, dimensions and aspect +# ratio has been provided for you. +meta_image: meta.png + +# At least one author is required. The values in this list correspond with the +# `id` properties of the team member files at /data/team/team. Create a file for +# yourself if you don't already have one. +authors: + - joe-duffy + +# At least one tag is required. Lowercase, hyphen-delimited is recommended. +tags: + - change-me + + +# The social copy used to promote this post on Twitter and Linkedin. These +# properties do not actually create the post and have no effect on the +# generated blog page. They are here strictly for reference. + +# Here are some examples of posts we have made in the past for inspiration: +# https://www.linkedin.com/feed/update/urn:li:activity:7171191945841561601 +# https://www.linkedin.com/feed/update/urn:li:activity:7169021002394296320 +# https://www.linkedin.com/feed/update/urn:li:activity:7155606616455737345 +# https://twitter.com/PulumiCorp/status/1763265391042654623 +# https://twitter.com/PulumiCorp/status/1762900472489185492 +# https://twitter.com/PulumiCorp/status/1755637618631405655 + +social: + twitter: + linkedin: + +# See the blogging docs at https://github.com/pulumi/docs/blob/master/BLOGGING.md +# for details, and please remove these comments before submitting for review. +--- + +What you put here will appear on the index page. In most cases, you'll also want to add a Read More link after this paragraph (though technically, that's optional. To do that, just add an HTML comment like the one below. + +<!--more--> + +And then everything _after_ that comment will appear on the post page itself. + +Either way, avoid using images or code samples [in the first 70 words](https://gohugo.io/content-management/summaries/#automatic-summary-splitting) of your post, as these may not render properly in summary contexts (e.g., on the blog home page or in social-media previews). + +## Writing the Post + +For help assembling the content of your post, see [BLOGGING.md](https://github.com/pulumi/docs/blob/master/BLOGGING.md). For general formatting guidelines, see the [Style Guide](https://github.com/pulumi/docs/blob/master/STYLE-GUIDE.md). + +## Code Samples + +```typescript +let bucket = new aws.s3.Bucket("stuff"); +... +``` + +## Images + + + +## Videos + +{{< youtube "kDB-YRKFfYE?rel=0" >}} + +Note the `?rel=0` param, which tells YouTube to suggest only videos from same channel. diff --git a/content/blog/sfsdfsfs/meta.png b/content/blog/sfsdfsfs/meta.png new file mode 100644 index 0000000000000000000000000000000000000000..44a346913c3498ce31b90f943b1e2830cd0ca816 GIT binary patch literal 24665 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 B?p6Q* literal 0 HcmV?d00001 diff --git a/package.json b/package.json index 6f032a6caa81c..104bd0b470a06 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "license": "Apache-2.0", "scripts": { "minify-css": "node scripts/minify-css.js", - "prepare": "husky" + "prepare": "husky", + "ts-node": "ts-node" }, "dependencies": { "@aws-sdk/client-s3": "^3.427.0", @@ -40,6 +41,9 @@ "zod": "^3.24.1", "zod-matter": "^0.1.1" }, + "resolutions": { + "@types/ms": "0.7.32" + }, "devDependencies": { "@types/js-yaml": "^4.0.9", "@types/markdownlint": "^0.18.0", diff --git a/scripts/lint/find-markdown.ts b/scripts/lint/find-markdown.ts index 6e952537dd10b..27ca3aa5ca468 100644 --- a/scripts/lint/find-markdown.ts +++ b/scripts/lint/find-markdown.ts @@ -29,7 +29,7 @@ export interface MarkdownFile { /** * Different modes for finding markdown files and determining if they're new */ -type FinderMode = 'git' | 'gha' | 'standard'; +export type FinderMode = 'git' | 'gha'; const AUTO_GENERATED_HEADING_REGEX = /^> This page was automatically generated\./m; @@ -69,54 +69,97 @@ function shouldExcludeByFrontMatter(frontMatter: FrontMatter | undefined): boole import { debug } from './utils'; /** - * Get list of files modified in the latest git commit + * Get list of files that are newly added in the current branch compared to base branch, + * including staged and unstaged changes. Handles both local git and GitHub Actions environments. */ -function getGitModifiedFiles(): Set<string> { +function getGitModifiedFiles(baseBranch?: string): Set<string> { try { debug('Getting git modified files...'); - const output = execSync('git diff-tree --no-commit-id --name-only -r HEAD', { encoding: 'utf8' }); - const set = new Set(output.split('\n').filter(Boolean)); - debug('Modified files:', set); - return set; - } catch (error) { - console.warn('Failed to get git modified files, treating all files as existing'); - return new Set<string>(); - } -} + const newFiles = new Set<string>(); + + // In GitHub Actions, use FETCH_HEAD since we just fetched the base branch + const isGHA = process.env.GITHUB_ACTIONS === 'true'; + const baseRef = isGHA ? 'FETCH_HEAD' : (baseBranch || process.env.BASE_BRANCH || 'master'); + debug('Using base ref:', baseRef); + + try { + // In GHA, we've just fetched the base branch to FETCH_HEAD, so this is safe + const diffOutput = execSync(`git diff --name-status HEAD ${baseRef}`, { encoding: 'utf8' }); + debug('Got diff output'); + diffOutput.split('\n') + .filter(line => line.startsWith('A\t')) + .map(line => line.split('\t')[1]) + .forEach(file => newFiles.add(file)); + } catch (error) { + debug('Diff failed:', error); + if (isGHA) { + // In GHA, if diff fails, something is wrong with our setup + throw error; + } + // In local dev, try to get staged/untracked files + debug('Falling back to staged/untracked files only'); + } -/** - * Get list of files modified in the current PR (GitHub Actions) - */ -function getGHAModifiedFiles(): Set<string> { - const eventPath = process.env.GITHUB_EVENT_PATH; - if (!eventPath) { - console.warn('No GITHUB_EVENT_PATH found, treating all files as existing'); - return new Set<string>(); - } + // In local dev, also look for staged and untracked files + if (!isGHA) { + try { + // Get new files from staged changes + const stagedFiles = execSync('git diff --name-status --cached', { encoding: 'utf8' }); + stagedFiles.split('\n') + .filter(line => line.startsWith('A\t')) + .map(line => line.split('\t')[1]) + .forEach(file => newFiles.add(file)); + + // Get untracked files + debug('Getting untracked files...'); + const untrackedFiles = execSync('git ls-files --others --exclude-standard --full-name', { encoding: 'utf8' }); + debug('Raw untracked files output:', untrackedFiles); + untrackedFiles.split('\n').filter(Boolean).forEach(file => newFiles.add(file)); + + // Also get untracked markdown files specifically + const untrackedMarkdown = execSync('git ls-files --others --exclude-standard --full-name "*.md"', { encoding: 'utf8' }); + debug('Raw untracked markdown files:', untrackedMarkdown); + untrackedMarkdown.split('\n').filter(Boolean).forEach(file => newFiles.add(file)); + } catch (error) { + debug('Failed to get staged/untracked files:', error); + } + } - try { - const event = JSON.parse(fs.readFileSync(eventPath, 'utf8')); - const files = event.pull_request?.changed_files || []; - return new Set(files); + debug('Found new files:', newFiles); + return newFiles; } catch (error) { - console.warn('Failed to get PR modified files, treating all files as existing'); + console.warn('Failed to get git modified files:', error); + if (process.env.GITHUB_ACTIONS === 'true') { + console.warn('Running in GitHub Actions - treating all files as existing'); + } else { + console.warn('Running locally - treating all files as existing'); + } return new Set<string>(); } } + + /** - * Find all markdown files in the given directory and its subdirectories. + * Find all markdown files in the given directory and its subdirectoriesA * Optionally marks files as new based on git/GHA context. */ export function findMarkdownFiles( rootDir: string, - mode: FinderMode = 'standard', - excludePaths: string[] = ['/content/docs/reference/pkg', '/content/registry'] + mode: FinderMode = 'git', + excludePaths: string[] = ['/content/docs/reference/pkg', '/content/registry', '/node_modules'] ): MarkdownFile[] { const files: MarkdownFile[] = []; - const modifiedFiles = mode === 'git' ? getGitModifiedFiles() - : mode === 'gha' ? getGHAModifiedFiles() - : new Set<string>(); + + // Determine which files are considered new based on mode + let modifiedFiles = new Set<string>(); + if (mode === 'git') { + modifiedFiles = getGitModifiedFiles(); + } else if (mode === 'gha') { + const baseBranch = process.env.BASE_BRANCH; + debug('GHA mode using base branch:', baseBranch); + modifiedFiles = getGitModifiedFiles(baseBranch); + } function isExcluded(filePath: string): boolean { return excludePaths.some(excludePath => filePath.includes(excludePath)); @@ -142,9 +185,11 @@ export function findMarkdownFiles( const content = fs.readFileSync(fullPath, 'utf8'); const frontMatter = parseFrontMatter(fullPath); if (!shouldExcludeByFrontMatter(frontMatter)) { + // Convert absolute path to relative for comparing with git modified files + const relPath = path.relative(process.cwd(), fullPath); files.push({ path: fullPath, - isNew: modifiedFiles.has(fullPath), + isNew: modifiedFiles.has(relPath), content, frontMatter }); @@ -159,8 +204,19 @@ export function findMarkdownFiles( // If run directly, output found files if (require.main === module) { - const mode = (process.argv[2] as FinderMode) || 'standard'; - const rootDir = process.argv[3] || '../../content'; - const files = findMarkdownFiles(rootDir, mode); - console.log(JSON.stringify(files, null, 2)); + const mode = (process.argv[2] as FinderMode) || 'gha'; + const showAll = process.argv.includes('--show-all'); + debug('Running in mode:', mode, 'show all:', showAll); + + // Find all markdown files + const files = findMarkdownFiles('.', mode); + + if (showAll) { + console.log('All markdown files (new files marked with *):') + console.log(JSON.stringify(files.map(f => `${f.isNew ? '*' : ' '} ${f.path}`), null, 2)); + } else { + const newFiles = files.filter(f => f.isNew).map(f => f.path); + console.log('New markdown files detected:'); + console.log(JSON.stringify(newFiles, null, 2)); + } } diff --git a/scripts/lint/lint.sh b/scripts/lint/lint.sh index 19678d8ce988a..70a32eedcc727 100755 --- a/scripts/lint/lint.sh +++ b/scripts/lint/lint.sh @@ -2,23 +2,35 @@ set -o errexit -o pipefail -# Get script directory -SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - DEBUG=0 +# Debug logging function +debug() { + if [ -n "$DEBUG" ]; then + echo "[DEBUG] $1" + fi +} + # Determine mode based on environment -if [ -n "$GITHUB_ACTIONS" ]; then +if [ -n "$BASE_BRANCH" ]; then MODE="gha" + debug "Using base branch: $BASE_BRANCH" else MODE="git" + debug "Using git mode (no base branch)" fi +# If in debug mode, show what files would be considered new +# if [ -n "$DEBUG" ]; then +# debug "Preview of new files:" +# yarn ts-node "./scripts/lint/find-markdown.ts" "$MODE" --show-all +# fi + # Run markdown linting with debug flag -DEBUG=$DEBUG ts-node "$SCRIPT_DIR/markdownlint-runner.ts" "$MODE" +DEBUG=$DEBUG yarn ts-node "./scripts/lint/markdownlint-runner.ts" "$MODE" # Run front matter validation -DEBUG=$DEBUG ts-node "$SCRIPT_DIR/validate-frontmatter.ts" "$MODE" +DEBUG=$DEBUG yarn ts-node "./scripts/lint/validate-frontmatter.ts" "$MODE" # Run prettier yarn prettier --check . diff --git a/scripts/lint/markdownlint-runner.ts b/scripts/lint/markdownlint-runner.ts index 2f10b7e1e6e9c..a9f1bd3caeee4 100644 --- a/scripts/lint/markdownlint-runner.ts +++ b/scripts/lint/markdownlint-runner.ts @@ -1,5 +1,5 @@ import * as path from 'path'; -import { findMarkdownFiles } from './find-markdown'; +import { findMarkdownFiles, FinderMode } from './find-markdown'; // Types for markdownlint type Token = { @@ -61,7 +61,7 @@ function groupLintErrorOutput(result: Record<string, LintError[]>): LintResult[] import { debug } from './utils'; // Get mode from command line args, defaulting to 'standard' -const mode = (process.argv[2] as 'git' | 'gha' | 'standard') || 'standard'; +const mode = (process.argv[2] as FinderMode) || 'git'; debug('Running in mode:', mode); // Get markdown files to lint diff --git a/scripts/lint/test-pr-event.json b/scripts/lint/test-pr-event.json new file mode 100644 index 0000000000000..6b51a6bab6289 --- /dev/null +++ b/scripts/lint/test-pr-event.json @@ -0,0 +1,32 @@ +{ + "pull_request": { + "number": 123, + "title": "Test PR", + "files": [ + { + "sha": "bbcd538c8e72b8c175046e27cc8f907076331401", + "filename": "content/blog/test-post/index.md", + "status": "added", + "additions": 103, + "deletions": 0, + "changes": 103 + }, + { + "sha": "abcd538c8e72b8c175046e27cc8f907076331402", + "filename": "content/blog/test-post/meta.png", + "status": "modified", + "additions": 0, + "deletions": 0, + "changes": 0 + } + ] + }, + "commits": [ + { + "id": "abc123", + "added": [ + "content/blog/another-post/index.md" + ] + } + ] +} diff --git a/scripts/lint/validate-frontmatter.ts b/scripts/lint/validate-frontmatter.ts index 3b8ab6bd86142..7952cbd396913 100644 --- a/scripts/lint/validate-frontmatter.ts +++ b/scripts/lint/validate-frontmatter.ts @@ -1,7 +1,7 @@ import { z } from 'zod'; import { parse as parseMatter } from 'zod-matter'; import * as path from 'path'; -import { MarkdownFile, findMarkdownFiles } from './find-markdown'; +import { MarkdownFile, findMarkdownFiles, FinderMode } from './find-markdown'; import { debug } from './utils'; // Schema for front matter validation @@ -205,7 +205,7 @@ export function runValidation( excludePaths: string[] = [] ): number { // Get mode from command line args, defaulting to 'standard' - const mode = (process.argv[2] as 'git' | 'gha' | 'standard') || 'standard'; + const mode = (process.argv[2] as FinderMode) || 'git'; debug('Starting frontmatter validation in mode:', mode); // Get markdown files to validate diff --git a/yarn.lock b/yarn.lock index 4f035308cf242..9e9e167cc81dc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1459,10 +1459,10 @@ dependencies: markdownlint "*" -"@types/ms@*": - version "2.1.0" - resolved "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz" - integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA== +"@types/ms@*", "@types/ms@0.7.32": + version "0.7.32" + resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.32.tgz#f6cd08939ae3ad886fcc92ef7f0109dacddf61ab" + integrity sha512-xPSg0jm4mqgEkNhowKgZFBNtwoEwF6gJ4Dhww+GFpm3IgtNseHQZ5IqdNwnquZEoANxyDAKDRAdVo4Z72VvD/g== "@types/node@*", "@types/node@>=8.9.0": version "18.7.18"