From 71b89806c9609d073dea8eab5a13ed576cbf7b0d Mon Sep 17 00:00:00 2001 From: Nick Alteen Date: Fri, 11 Jul 2025 13:19:35 -0400 Subject: [PATCH] feat: add Copilot and unit test prompts for generating documentation and tests --- .github/copilot-instructions.md | 127 ++++++++++++++++++ .../prompts/create-release-notes.prompt.md | 40 ++++++ .github/prompts/unit-test.prompt.md | 90 +++++++++++++ 3 files changed, 257 insertions(+) create mode 100644 .github/copilot-instructions.md create mode 100644 .github/prompts/create-release-notes.prompt.md create mode 100644 .github/prompts/unit-test.prompt.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..87bb894 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,127 @@ +# Copilot Instructions + +This GitHub Action is written in JavaScript and transpiled to a single file. +Both the JavaScript sources and the **generated** JavaScript code are contained +in this repository. The JavaScript sources are contained in the `src` directory +and the code invoked by GitHub Actions is contained in the `dist` directory. A +GitHub Actions workflow checks that the JavaScript code in `dist` is up-to-date. +Therefore, you should not review any changes to the contents of the `dist` +folder and it is expected that the JavaScript code in `dist` closely mirrors the +code it is generated from. + +## Repository Structure + +| Path | Description | +| -------------------- | -------------------------------------------------------- | +| `__fixtures__/` | Unit Test Fixtures | +| `__tests__/` | Unit Tests | +| `.devcontainer/` | Development Container Configuration | +| `.github/` | GitHub Configuration | +| `.licenses/` | License Information | +| `.vscode/` | VSCode Configuration | +| `badges/` | Badges for README | +| `dist/` | Generated JavaScript Code | +| `src/` | JavaScript Source Code | +| `.env.example` | Environment Variables Example for `@github/local-action` | +| `.licensed.yml` | Licensed Configuration | +| `.markdown-lint.yml` | Markdown Linter Configuration | +| `.node-version` | Node.js Version Configuration | +| `.prettierrc.yml` | Prettier Formatter Configuration | +| `.yaml-lint.yml` | YAML Linter Configuration | +| `action.yml` | GitHub Action Metadata | +| `CODEOWNERS` | Code Owners File | +| `eslint.config.mjs` | ESLint Configuration | +| `jest.config.js` | Jest Configuration | +| `LICENSE` | License File | +| `package.json` | NPM Package Configuration | +| `README.md` | Project Documentation | +| `rollup.config.js` | Rollup Bundler Configuration | + +## Environment Setup + +Install dependencies by running: + +```bash +npm install +``` + +## Testing + +Ensure all unit tests pass by running: + +```bash +npm run test +``` + +Unit tests should exist in the `__tests__` directory. They are powered by +`jest`. Fixtures should be placed in the `__fixtures__` directory. + +## Bundling + +Any time files in the `src` directory are changed, you should run the following +command to bundle the JavaScript code into the `dist` directory: + +```bash +npm run bundle +``` + +## General Coding Guidelines + +- Follow standard JavaScript coding conventions and best practices +- Changes should maintain consistency with existing patterns and style +- Document changes clearly and thoroughly, including updates to existing + comments when appropriate +- Do not include basic, unnecessary comments that simply restate what the code + is doing (focus on explaining _why_, not _what_) +- Use consistent error handling patterns throughout the codebase +- Keep functions focused and manageable +- Use descriptive variable and function names that clearly convey their purpose +- Use JSDoc comments to document functions, classes, and complex logic +- After doing any refactoring, ensure to run `npm run test` to ensure that all + tests still pass and coverage requirements are met +- When suggesting code changes, always opt for the most maintainable approach. + Try your best to keep the code clean and follow "Don't Repeat Yourself" (DRY) + principles +- Avoid unnecessary complexity and always consider the long-term maintainability + of the code +- When writing unit tests, try to consider edge cases as well as the main path + of success. This will help ensure that the code is robust and can handle + unexpected inputs or situations +- Use the `@actions/core` package for logging over `console` to ensure + compatibility with GitHub Actions logging features + +### Versioning + +GitHub Actions are versioned using branch and tag names. Please ensure the +version in the project's `package.json` is updated to reflect the changes made +in the codebase. The version should follow +[Semantic Versioning](https://semver.org/) principles. + +## Pull Request Guidelines + +When creating a pull request (PR), please ensure that: + +- Keep changes focused and minimal (avoid large changes, or consider breaking + them into separate, smaller PRs) +- Formatting checks pass +- Linting checks pass +- Unit tests pass and coverage requirements are met +- The action has been transpiled to JavaScript and the `dist` directory is + up-to-date with the latest changes in the `src` directory +- If necessary, the `README.md` file is updated to reflect any changes in + functionality or usage + +The body of the PR should include: + +- A summary of the changes +- A special note of any changes to dependencies +- A link to any relevant issues or discussions +- Any additional context that may be helpful for reviewers + +## Code Review Guidelines + +When performing a code review, please follow these guidelines: + +- If there are changes that modify the functionality/usage of the action, + validate that there are changes in the `README.md` file that document the new + or modified functionality diff --git a/.github/prompts/create-release-notes.prompt.md b/.github/prompts/create-release-notes.prompt.md new file mode 100644 index 0000000..b346720 --- /dev/null +++ b/.github/prompts/create-release-notes.prompt.md @@ -0,0 +1,40 @@ +--- +mode: agent +tools: ['changes', 'codebase', 'github'] +description: Generate release notes for updates to the repository. +--- + +# Create Release Notes + +You are an expert technical writer tasked with creating release notes for +updates to this repository. Your specific task is to generate release notes that +are clear, concise, and useful for developers and users of the project. + +## Guidelines + +Ensure you adhere to the following guidelines when creating release notes: + +- Use a clear and consistent format for the release notes +- Include a summary of the changes made in the release +- Highlight any new features, improvements, or bug fixes +- If applicable, include instructions for upgrading or migrating to the new + version +- Use technical language that is appropriate for the audience, but avoid jargon + that may not be understood by all users +- Ensure that the release notes are easy to read and navigate +- Include relevant issue or PR numbers where applicable +- Use proper Markdown formatting +- Use code blocks for commands, configuration examples, or code changes +- Use note and warning callouts for important information + +## Versioning + +GitHub Actions are versioned using branch and tag names. The version in the +project's `package.json` should reflect the changes made in the codebase and +follow [Semantic Versioning](https://semver.org/) principles. Depending on the +nature of the changes, please make sure to adjust the release notes accordingly: + +- For **major** changes, include a detailed description of the breaking changes + and how users can adapt to them +- For **minor** changes, highlight new features and improvements +- For **patch** changes, focus on bug fixes and minor improvements diff --git a/.github/prompts/unit-test.prompt.md b/.github/prompts/unit-test.prompt.md new file mode 100644 index 0000000..c2e7c9d --- /dev/null +++ b/.github/prompts/unit-test.prompt.md @@ -0,0 +1,90 @@ +--- +mode: agent +tools: ['codebase', 'github'] +description: Generate unit tests for one or more files in the repository. +--- + +# Create Unit Test(s) + +You are an expert software engineer tasked with creating unit tests for the +repository. Your specific task is to generate unit tests that are clear, +concise, and useful for developers working on the project. + +## Guidelines + +Ensure you adhere to the following guidelines when creating unit tests: + +- Use a clear and consistent format for the unit tests +- Include a summary of the functionality being tested +- Use descriptive test names that clearly convey their purpose +- Ensure tests cover both the main path of success and edge cases +- Use proper assertions to validate the expected outcomes +- Use `jest` for writing and running tests +- Place unit tests in the `__tests__` directory +- Use fixtures for any necessary test data, placed in the `__fixtures__` + directory + +## Example + +Use the following as an example of how to structure your unit tests: + +```javascript +/** + * Unit tests for the action's main functionality, src/main.js + */ +import { jest } from '@jest/globals' +import * as core from '../__fixtures__/core.js' +import { wait } from '../__fixtures__/wait.js' + +// Mocks should be declared before the module being tested is imported. +jest.unstable_mockModule('@actions/core', () => core) +jest.unstable_mockModule('../src/wait.js', () => ({ wait })) + +// The module being tested should be imported dynamically. This ensures that the +// mocks are used in place of any actual dependencies. +const { run } = await import('../src/main.js') + +describe('main.js', () => { + beforeEach(() => { + // Set the action's inputs as return values from core.getInput(). + core.getInput.mockImplementation(() => '500') + + // Mock the wait function so that it does not actually wait. + wait.mockImplementation(() => Promise.resolve('done!')) + }) + + afterEach(() => { + jest.resetAllMocks() + }) + + it('Sets the time output', async () => { + await run() + + // Verify the time output was set. + expect(core.setOutput).toHaveBeenNthCalledWith( + 1, + 'time', + // Simple regex to match a time string in the format HH:MM:SS. + expect.stringMatching(/^\d{2}:\d{2}:\d{2}/) + ) + }) + + it('Sets a failed status', async () => { + // Clear the getInput mock and return an invalid value. + core.getInput.mockClear().mockReturnValueOnce('this is not a number') + + // Clear the wait mock and return a rejected promise. + wait + .mockClear() + .mockRejectedValueOnce(new Error('milliseconds is not a number')) + + await run() + + // Verify that the action was marked as failed. + expect(core.setFailed).toHaveBeenNthCalledWith( + 1, + 'milliseconds is not a number' + ) + }) +}) +```