Skip to content

Commit 8854db9

Browse files
committed
Merge branch 'main' into add-work-item-linkage-from-branch-name
2 parents 5803d42 + b4b2805 commit 8854db9

8 files changed

Lines changed: 285 additions & 159 deletions

File tree

.github/copilot-instructions.md

Lines changed: 89 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -1,172 +1,136 @@
11
# GitHub Copilot Instructions for Node.js Actions
22

3+
<!-- This file is managed by joshjohanning/sync-github-repo-settings. Do not edit directly — changes will be overwritten. -->
4+
35
## Project Overview
46

5-
This is a Node.js GitHub Action template with ESLint, Prettier, Jest testing, and ncc bundling. Follow these guidelines when making changes.
7+
This is a Node.js GitHub Action with ESLint, Prettier, Jest testing, and ncc bundling. Follow these guidelines when making changes.
68

7-
## Code Quality Standards
9+
## Critical Rules
810

9-
### ESLint Configuration
11+
These rules prevent CI failures and broken releases. **Never skip them.**
1012

11-
- Follow the existing ESLint configuration in `eslint.config.js`
12-
- Use ES modules (`import`/`export`) consistently
13-
- Prefer `const` over `let` when variables don't change
14-
- Use descriptive variable names and JSDoc comments for functions
15-
- Handle errors gracefully with try/catch blocks
13+
- **MUST:** Run `npm run all` before committing. This runs format, lint, test, package, and badge generation. Fix any failures before proceeding.
14+
- **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.
15+
- **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.
16+
- **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`.
17+
- **MUST:** When updating Node.js support, update `runs.using` in `action.yml`, `engines.node` in `package.json`, and CI matrices together.
18+
- **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 }}`.
19+
- **NEVER:** Log tokens, secrets, or authenticated URLs. Use `core.setSecret()` to mask sensitive values.
20+
- **NEVER:** Use `console.log` or `console.error`. Use `core.info()`, `core.warning()`, `core.error()`, and `core.debug()` instead.
1621

17-
### Prettier Formatting
22+
## Action Entry Point Pattern
1823

19-
- Code is automatically formatted with Prettier
20-
- Run `npm run format:write` to format all files
21-
- Use single quotes for strings unless they contain single quotes
22-
- Line length limit is enforced by Prettier config
24+
- Main logic lives in `src/index.js` with an async `run()` function and top-level try/catch
25+
- Use `core.setFailed(error.message)` in the catch block — do not use `process.exit(1)`
26+
- Export helper functions for testability
27+
- If the action calls GitHub APIs, initialize Octokit with `baseUrl` for GHES/GHEC-DR support
2328

24-
### Import Organization
29+
## Input and Output Handling
2530

26-
```javascript
27-
// Always follow this import order:
28-
import * as core from '@actions/core';
29-
import * as github from '@actions/github';
30-
import { Octokit } from '@octokit/rest';
31-
// ... other imports
32-
```
31+
### Inputs
3332

34-
## Testing Guidelines
33+
- Use `core.getInput()` for string inputs and `core.getBooleanInput()` for boolean inputs
34+
- Validate inputs early in the function
35+
- Log input values for debugging (except sensitive data)
36+
- Every input in `action.yml` must be documented in the README
3537

36-
### Jest Test Structure
38+
### Outputs
3739

38-
- Use ES modules with `jest.unstable_mockModule()` for mocking
39-
- Mock `@actions/core`, `@actions/github`, and external APIs
40-
- Test both success and error scenarios
41-
- Use descriptive test names that explain the behavior
40+
- Set outputs using `core.setOutput()`
41+
- Output names must match what's defined in `action.yml`
4242

43-
### Mock Patterns
43+
## Error Handling
4444

45-
```javascript
46-
// Always mock modules before importing
47-
jest.unstable_mockModule('@actions/core', () => mockCore);
48-
const { functionToTest } = await import('../src/index.js');
49-
```
45+
- Use `core.setFailed()` for fatal action failures
46+
- Use `core.warning()` for non-fatal issues
47+
- Check `error.status` for API errors — don't match on error message strings
48+
- Catch errors at call boundaries; let helper functions throw contextual errors rather than calling `core.setFailed()` directly
5049

51-
### Test Coverage
50+
## GitHub API Usage
5251

53-
- Write unit tests for all exported functions
54-
- Test error handling paths
55-
- Mock external dependencies (GitHub API, file system, etc.)
56-
- Aim for meaningful assertions, not just code coverage
52+
### Octokit Initialization
5753

58-
## GitHub Actions Patterns
54+
- Initialize with `baseUrl` for GHES/GHEC-DR support: `new Octokit({ auth: token, baseUrl: apiUrl })`
55+
- GHES/GHE documentation doesn't typically need to be called out separately in the README unless there are specific differences to highlight
5956

60-
### Node Runtime
57+
### Pagination
6158

62-
- 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)
63-
- Use the same Node.js runtime version configured in this repo's `action.yml` for `runs.using`
64-
- 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
59+
- Use `octokit.paginate()` for any endpoint that returns a list
6560

66-
### Input Handling
61+
### Rate Limiting
6762

68-
- Use our custom `getInput()` function for reliable local/CI compatibility
69-
- Validate inputs early in the function
70-
- Provide sensible defaults where appropriate
71-
- Log input values for debugging (except sensitive data)
63+
- When iterating across many repos/resources, avoid unbounded parallel API calls — batch or serialize to reduce rate-limit pressure
7264

73-
### Output Setting
65+
## Logging and Job Summaries
7466

75-
- Always set outputs using `core.setOutput()`
76-
- Use descriptive output names that match `action.yml`
77-
- Include outputs in job summaries when available
67+
### Structured Logging
7868

79-
### Error Handling
69+
- Use `core.info()` for normal output, `core.debug()` for verbose details
70+
- Use `core.startGroup()` / `core.endGroup()` for collapsible log sections when processing multiple items
8071

81-
- Use `core.setFailed()` for action failures
82-
- Use `core.warning()` for non-fatal issues
83-
- Catch and handle API errors gracefully
84-
- Provide helpful error messages
72+
### Job Summaries
8573

86-
### Local Development Support
74+
- Use `core.summary` to add rich output to the Actions UI when summarizing key data or findings
8775

88-
- Support running locally with environment variables
89-
- Handle missing GitHub Actions environment gracefully
90-
- Provide clear documentation for local testing
76+
## Security
9177

92-
## File Organization
78+
- If the action performs git operations with tokens, sanitize error messages to strip embedded credentials before logging
79+
- Follow principle of least privilege for token permissions
80+
- Document required permissions in the README
81+
- Document when using a GitHub App would be more appropriate than `github.token` or a PAT
9382

94-
### Source Structure
83+
## Testing
9584

96-
- Main logic in `src/index.js`
97-
- Export functions for testing
98-
- Keep functions focused and single-purpose
99-
- Use JSDoc comments for all exported functions
85+
### Jest with ES Modules
10086

101-
### Build Process
87+
- Use `jest.unstable_mockModule()` for ESM mocking — mocks must be registered **before** dynamic imports:
10288

103-
- Use `npm run package` to bundle with ncc
104-
- Don't commit the bundled `dist/` directory (during publishing this gets published to **tag-only**)
105-
- Run `npm run all` before committing (format, lint, test, package, and badge updating)
89+
```javascript
90+
jest.unstable_mockModule('@actions/core', () => ({
91+
getInput: jest.fn(),
92+
setOutput: jest.fn(),
93+
setFailed: jest.fn(),
94+
info: jest.fn(),
95+
warning: jest.fn()
96+
}));
10697

107-
### Dependency and Version Changes
98+
const core = await import('@actions/core');
99+
const { functionToTest } = await import('../src/index.js');
100+
```
108101

109-
- When bumping versions or changing dependencies, run `npm install` first to sync the `package-lock.json`, then run `npm run all`
110-
- Do not skip these steps -- a mismatched `package-lock.json` or failing checks will break CI
102+
### Test Environment Setup
111103

112-
## Documentation Standards
104+
- Set `process.env` variables **before** importing the module under test when the module validates config at load time
105+
- Reset mocks and environment between tests
113106

114-
### README and action.yml Updates
107+
### What to Test
115108

116-
- **Always update `README.md` and `action.yml` when adding, removing, or changing inputs, outputs, or behavior** -- do not forget this step
117-
- Keep usage examples in the README in sync with `action.yml`
118-
- Document all inputs and outputs in both `action.yml` (descriptions/defaults) and `README.md` (usage table/examples)
119-
- Include local development instructions
120-
- Update feature lists when adding functionality
109+
- Test both success and error paths
110+
- Assert `core.setFailed`, `core.warning`, and `core.setOutput` calls explicitly
111+
- Mock external dependencies (GitHub API, file system, etc.)
112+
- Export helper functions from `src/index.js` to make them individually testable
121113

122-
### Code Comments
114+
## Build and Release
123115

124-
- Use JSDoc for function documentation
125-
- Include parameter types and return types
126-
- Add inline comments for complex logic
127-
- Document environment variable requirements
116+
### Build Process
128117

129-
## Dependencies
118+
- Use `npm run package` to bundle with ncc into `dist/`
119+
- 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
120+
- Users consume the action via version tags: `uses: owner/action@v1`
130121

131-
### Adding New Dependencies
122+
### Dependencies
132123

133124
- Prefer `@actions/*` packages for GitHub Actions functionality
134-
- Keep dependencies minimal and well-maintained
135-
- Update both `dependencies` and `devDependencies` appropriately
136-
- Test that bundling still works after adding dependencies
137-
138-
### Version Management
139-
140-
- **Always increment the package.json version for each change**
141-
- Use semantic versioning (major.minor.patch)
142-
- Increment patch for bug fixes, minor for new features, major for breaking changes
143-
- Update version before creating releases or publishing changes
144-
145-
### GitHub API Usage
146-
147-
- Use `@octokit/rest` for REST API calls
148-
- Use `@actions/github` for context and helpers
149-
- Handle rate limiting and authentication errors
150-
- Cache API responses when appropriate
151-
- Use pagination when necessary
152-
153-
### GitHub Instance Support
154-
155-
- **Always support GitHub.com, GHES, and GHEC-DR** using `github-api-url` input with default `${{ github.api_url }}`
156-
- Initialize Octokit with a fallback `baseUrl`: `new Octokit({ auth: token, baseUrl: apiUrl || 'https://api.github.com' })`
157-
- GHES/GHE documentation doesn't typically need to be called out separately in the README unless there are specific differences to highlight
158-
159-
## Performance Considerations
125+
- Use `@octokit/rest` for REST API calls and `@actions/github` for context and helpers
126+
- Test that ncc bundling still works after adding dependencies
127+
- Use semantic versioning: patch for bug fixes, minor for new features, major for breaking changes
160128

161-
- Avoid unnecessary API calls (respect rate limits)
162-
- Use efficient data structures for large datasets
163-
- Handle large datasets with pagination and streaming when possible
164-
- Cache API responses when appropriate to reduce redundant calls
129+
## Code Style
165130

166-
## Security Best Practices
167-
168-
- Never log sensitive data (tokens, secrets)
169-
- Use `core.setSecret()` to mask sensitive values
170-
- Validate and sanitize user inputs
171-
- Follow principle of least privilege for token permissions
172-
- Document when using a GitHub App would be more appropriate than `github.token` or a PAT
131+
- Follow the existing ESLint configuration in `eslint.config.js`
132+
- Use ES modules (`import`/`export`) consistently
133+
- Code is automatically formatted with Prettier — run `npm run format:write` to format
134+
- 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)
135+
- Use JSDoc comments with parameter types and return types for exported functions
136+
- Organize imports: `@actions/*` first, then `@octokit/*`, then other dependencies, then local imports

0 commit comments

Comments
 (0)