From c20e244778f4ddb9764626515f61a85223f3ce8d Mon Sep 17 00:00:00 2001 From: "joshjohanning-repo-settings-sync[bot]" <237077283+joshjohanning-repo-settings-sync[bot]@users.noreply.github.com> Date: Sun, 29 Mar 2026 16:16:49 +0000 Subject: [PATCH 1/3] chore: update .github/copilot-instructions.md --- .github/copilot-instructions.md | 212 +++++++++++++------------------- 1 file changed, 87 insertions(+), 125 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index d5c7e4d..c38de4d 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -2,171 +2,133 @@ ## Project Overview -This is a Node.js GitHub Action template with ESLint, Prettier, Jest testing, and ncc bundling. Follow these guidelines when making changes. +This is a Node.js GitHub Action with ESLint, Prettier, Jest testing, and ncc bundling. Follow these guidelines when making changes. -## Code Quality Standards +## Critical Rules -### ESLint Configuration +These rules prevent CI failures and broken releases. **Never skip them.** -- Follow the existing ESLint configuration in `eslint.config.js` -- Use ES modules (`import`/`export`) consistently -- Prefer `const` over `let` when variables don't change -- Use descriptive variable names and JSDoc comments for functions -- Handle errors gracefully with try/catch blocks +- **MUST:** Run `npm run all` before committing. This runs format, lint, test, package, and badge generation. Fix any failures before proceeding. +- **MUST:** Bump `package.json` version when the published artifact changes: action behavior, runtime requirements, production dependencies, inputs/outputs, or bundled code. Do **not** bump for docs-only, tests-only, CI-only, or devDependency-only changes. +- **MUST:** When bumping versions or changing dependencies, run `npm install` first to sync `package-lock.json`, then run `npm run all`. A mismatched lockfile breaks CI. +- **MUST:** Update `README.md` and `action.yml` when adding, removing, or changing inputs, outputs, or behavior. Keep usage examples in the README in sync with `action.yml`. +- **MUST:** When updating Node.js support, update `runs.using` in `action.yml`, `engines.node` in `package.json`, and CI matrices together. +- **MUST:** If the action calls GitHub APIs, support GitHub.com, GHES, and GHEC-DR using a `github-api-url` input with default `${{ github.api_url }}`. +- **NEVER:** Log tokens, secrets, or authenticated URLs. Use `core.setSecret()` to mask sensitive values. +- **NEVER:** Use `console.log` or `console.error`. Use `core.info()`, `core.warning()`, `core.error()`, and `core.debug()` instead. -### Prettier Formatting +## Action Entry Point Pattern -- Code is automatically formatted with Prettier -- Run `npm run format:write` to format all files -- Use single quotes for strings unless they contain single quotes -- Line length limit is enforced by Prettier config +- Main logic lives in `src/index.js` with an async `run()` function and top-level try/catch +- Use `core.setFailed(error.message)` in the catch block — do not use `process.exit(1)` +- Export helper functions for testability +- If the action calls GitHub APIs, initialize Octokit with `baseUrl` for GHES/GHEC-DR support -### Import Organization +## Input and Output Handling -```javascript -// Always follow this import order: -import * as core from '@actions/core'; -import * as github from '@actions/github'; -import { Octokit } from '@octokit/rest'; -// ... other imports -``` +### Inputs -## Testing Guidelines +- Use `core.getInput()` for string inputs and `core.getBooleanInput()` for boolean inputs +- Validate inputs early in the function +- Log input values for debugging (except sensitive data) +- Every input in `action.yml` must be documented in the README -### Jest Test Structure +### Outputs -- Use ES modules with `jest.unstable_mockModule()` for mocking -- Mock `@actions/core`, `@actions/github`, and external APIs -- Test both success and error scenarios -- Use descriptive test names that explain the behavior +- Set outputs using `core.setOutput()` +- Output names must match what's defined in `action.yml` -### Mock Patterns +## Error Handling -```javascript -// Always mock modules before importing -jest.unstable_mockModule('@actions/core', () => mockCore); -const { functionToTest } = await import('../src/index.js'); -``` +- Use `core.setFailed()` for fatal action failures +- Use `core.warning()` for non-fatal issues +- Check `error.status` for API errors — don't match on error message strings +- Catch errors at call boundaries; let helper functions throw contextual errors rather than calling `core.setFailed()` directly -### Test Coverage +## GitHub API Usage -- Write unit tests for all exported functions -- Test error handling paths -- Mock external dependencies (GitHub API, file system, etc.) -- Aim for meaningful assertions, not just code coverage +### Octokit Initialization -## GitHub Actions Patterns +- Initialize with `baseUrl` for GHES/GHEC-DR support: `new Octokit({ auth: token, baseUrl: apiUrl })` +- GHES/GHE documentation doesn't typically need to be called out separately in the README unless there are specific differences to highlight -### Node Runtime +### Pagination -- Only use Node.js runtimes officially supported by GitHub Actions (see [GitHub Actions documentation](https://docs.github.com/en/actions/sharing-automations/creating-actions/metadata-syntax-for-github-actions#runs-for-javascript-actions) for current supported versions) -- Use the same Node.js runtime version configured in this repo's `action.yml` for `runs.using` -- When updating Node.js support, update `runs.using` in `action.yml`, the `engines.node` range in `package.json`, and CI/test matrices together to stay consistent +- Use `octokit.paginate()` for any endpoint that returns a list -### Input Handling +### Rate Limiting -- Use our custom `getInput()` function for reliable local/CI compatibility -- Validate inputs early in the function -- Provide sensible defaults where appropriate -- Log input values for debugging (except sensitive data) +- When iterating across many repos/resources, avoid unbounded parallel API calls — batch or serialize to reduce rate-limit pressure -### Output Setting +## Logging and Job Summaries -- Always set outputs using `core.setOutput()` -- Use descriptive output names that match `action.yml` -- Include outputs in job summaries when available +### Structured Logging -### Error Handling +- Use `core.info()` for normal output, `core.debug()` for verbose details +- Use `core.startGroup()` / `core.endGroup()` for collapsible log sections when processing multiple items -- Use `core.setFailed()` for action failures -- Use `core.warning()` for non-fatal issues -- Catch and handle API errors gracefully -- Provide helpful error messages +### Job Summaries -### Local Development Support +- Use `core.summary` to add rich output to the Actions UI when summarizing key data or findings -- Support running locally with environment variables -- Handle missing GitHub Actions environment gracefully -- Provide clear documentation for local testing +## Security -## File Organization +- If the action performs git operations with tokens, sanitize error messages to strip embedded credentials before logging +- Follow principle of least privilege for token permissions +- Document required permissions in the README +- Document when using a GitHub App would be more appropriate than `github.token` or a PAT -### Source Structure +## Testing -- Main logic in `src/index.js` -- Export functions for testing -- Keep functions focused and single-purpose -- Use JSDoc comments for all exported functions +### Jest with ES Modules -### Build Process +- Use `jest.unstable_mockModule()` for ESM mocking — mocks must be registered **before** dynamic imports: -- Use `npm run package` to bundle with ncc -- Don't commit the bundled `dist/` directory (during publishing this gets published to **tag-only**) -- Run `npm run all` before committing (format, lint, test, package, and badge updating) + ```javascript + jest.unstable_mockModule('@actions/core', () => ({ + getInput: jest.fn(), + setOutput: jest.fn(), + setFailed: jest.fn(), + info: jest.fn(), + warning: jest.fn() + })); -### Dependency and Version Changes + const core = await import('@actions/core'); + const { functionToTest } = await import('../src/index.js'); + ``` -- When bumping versions or changing dependencies, run `npm install` first to sync the `package-lock.json`, then run `npm run all` -- Do not skip these steps -- a mismatched `package-lock.json` or failing checks will break CI +### Test Environment Setup -## Documentation Standards +- Set `process.env` variables **before** importing the module under test when the module validates config at load time +- Reset mocks and environment between tests -### README and action.yml Updates +### What to Test -- **Always update `README.md` and `action.yml` when adding, removing, or changing inputs, outputs, or behavior** -- do not forget this step -- Keep usage examples in the README in sync with `action.yml` -- Document all inputs and outputs in both `action.yml` (descriptions/defaults) and `README.md` (usage table/examples) -- Include local development instructions -- Update feature lists when adding functionality +- Test both success and error paths +- Assert `core.setFailed`, `core.warning`, and `core.setOutput` calls explicitly +- Mock external dependencies (GitHub API, file system, etc.) +- Export helper functions from `src/index.js` to make them individually testable -### Code Comments +## Build and Release -- Use JSDoc for function documentation -- Include parameter types and return types -- Add inline comments for complex logic -- Document environment variable requirements +### Build Process -## Dependencies +- Use `npm run package` to bundle with ncc into `dist/` +- The `dist/` directory is not committed to the main branch — it is built by CI and published for Git tags (for example, release tags like `v1.2.3` or major-version tags like `v1`) by the publish workflow +- Users consume the action via version tags: `uses: owner/action@v1` -### Adding New Dependencies +### Dependencies - Prefer `@actions/*` packages for GitHub Actions functionality -- Keep dependencies minimal and well-maintained -- Update both `dependencies` and `devDependencies` appropriately -- Test that bundling still works after adding dependencies - -### Version Management - -- **Always increment the package.json version for each change** -- Use semantic versioning (major.minor.patch) -- Increment patch for bug fixes, minor for new features, major for breaking changes -- Update version before creating releases or publishing changes - -### GitHub API Usage - -- Use `@octokit/rest` for REST API calls -- Use `@actions/github` for context and helpers -- Handle rate limiting and authentication errors -- Cache API responses when appropriate -- Use pagination when necessary - -### GitHub Instance Support - -- **Always support GitHub.com, GHES, and GHEC-DR** using `github-api-url` input with default `${{ github.api_url }}` -- Initialize Octokit with a fallback `baseUrl`: `new Octokit({ auth: token, baseUrl: apiUrl || 'https://api.github.com' })` -- GHES/GHE documentation doesn't typically need to be called out separately in the README unless there are specific differences to highlight - -## Performance Considerations +- Use `@octokit/rest` for REST API calls and `@actions/github` for context and helpers +- Test that ncc bundling still works after adding dependencies +- Use semantic versioning: patch for bug fixes, minor for new features, major for breaking changes -- Avoid unnecessary API calls (respect rate limits) -- Use efficient data structures for large datasets -- Handle large datasets with pagination and streaming when possible -- Cache API responses when appropriate to reduce redundant calls +## Code Style -## Security Best Practices - -- Never log sensitive data (tokens, secrets) -- Use `core.setSecret()` to mask sensitive values -- Validate and sanitize user inputs -- Follow principle of least privilege for token permissions -- Document when using a GitHub App would be more appropriate than `github.token` or a PAT +- Follow the existing ESLint configuration in `eslint.config.js` +- Use ES modules (`import`/`export`) consistently +- Code is automatically formatted with Prettier — run `npm run format:write` to format +- Use single quotes for strings +- Use JSDoc comments with parameter types and return types for exported functions +- Organize imports: `@actions/*` first, then `@octokit/*`, then other dependencies, then local imports From 4953365e8e1238d0ee9f0136b14f6918fa73daf9 Mon Sep 17 00:00:00 2001 From: "joshjohanning-repo-settings-sync[bot]" <237077283+joshjohanning-repo-settings-sync[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 19:06:17 +0000 Subject: [PATCH 2/3] chore: update .github/copilot-instructions.md --- .github/copilot-instructions.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index c38de4d..1d4d50c 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,5 +1,7 @@ # GitHub Copilot Instructions for Node.js Actions + + ## Project Overview This is a Node.js GitHub Action with ESLint, Prettier, Jest testing, and ncc bundling. Follow these guidelines when making changes. From f11dd56619954f6126de1f622ba0246f21f7741a Mon Sep 17 00:00:00 2001 From: "joshjohanning-repo-settings-sync[bot]" <237077283+joshjohanning-repo-settings-sync[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 19:34:48 +0000 Subject: [PATCH 3/3] chore: update .github/copilot-instructions.md --- .github/copilot-instructions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 1d4d50c..ab6eafe 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -131,6 +131,6 @@ These rules prevent CI failures and broken releases. **Never skip them.** - Follow the existing ESLint configuration in `eslint.config.js` - Use ES modules (`import`/`export`) consistently - Code is automatically formatted with Prettier — run `npm run format:write` to format -- Use single quotes for strings +- Use single quotes for strings - when a string contains embedded single quotes (e.g., `Invalid 'days' input`), use a template literal instead of escaped quotes or double quotes (do not modify ESLint or Prettier config to resolve quote conflicts) - Use JSDoc comments with parameter types and return types for exported functions - Organize imports: `@actions/*` first, then `@octokit/*`, then other dependencies, then local imports