Thank you for your interest in contributing to the UKHSA API Guidelines! This repository contains guidelines and best practices for designing, developing, and maintaining APIs at UKHSA.
- Contributing to UKHSA API Guidelines
Please read the Code of Conduct before contributing.
If you're an external contributor make sure to fork this project first
If you are a member of the ukhsa-collaboration GitHub organisation, you can clone the repository directly:
git clone https://github.com/ukhsa-collaboration/standards-api.git
cd standards-apiOtherwise, if you are an external contributor, you can clone your fork:
git clone https://github.com/YOUR-USERNAME/standards-api.git
cd standards-apiBefore you begin, ensure you have the following installed:
| Tool | Version | Description |
|---|---|---|
| Node.js / npm | Latest LTS |
Required for packaging and testing the linting ruleset. |
| Vacuum | Latest |
CLI for running the UKHSA linting ruleset. |
You can install npm and Vacuum CLI using your system's package manager or download them from their respective websites.
You can verify your installations with:
node --version
npm --version
vacuum --versioninstall the required dependencies with the following command:
npm installTo transpile TypeScript files to JavaScript:
npm run buildBuild the Vacuum-compatible functions (used by the linter at runtime) with:
npm run build:functions:cjsThis generates .js files in ./dist and produces Vacuum wrapper functions in ./dist/functions.
/docs/- Documentation content written in Markdown/docs/api-design-guidelines/- API design guidelines content/docs/linting-rules/- Documentation for API linting rules/example/- Example OpenAPI specifications/src/functions/- JavaScript functions used by the linting rulesukhsa.oas.rules.yml- UKHSA-specific linting ruleszalando.oas.rules.yml- Zalando API guidelines rules
- Check the Issues section for open tasks
- Look for issues tagged with
good first issueif you're new to the project
All commits to this repository MUST be signed with a GPG key to verify the committer's identity. This helps ensure the security and integrity of the codebase.
To set up signed commits:
gpg --full-generate-key# List your GPG keys to get the ID
gpg --list-secret-keys --keyid-format=long
# Configure Git to use your key (replace KEY_ID with your GPG key ID)
git config --global user.signingkey KEY_ID
# Enable commit signing by default
git config --global commit.gpgsign true- Export your public key:
gpg --armor --export KEY_ID - Add this key to your GitHub account under Settings > SSH and GPG keys
# If you've enabled signing by default, just commit normally
git commit -m "Your commit message"
# Or explicitly sign a commit
git commit -S -m "Your commit message"For more information, see GitHub's documentation on signing commits.
Before opening a new issue:
- Search existing issues to avoid duplicates
- Use issue templates if available
- Be clear and specific about:
- What needs to be changed/added
- Why it's important
- Any relevant context
-
Create a new branch for your work:
git checkout -b feature/your-feature-name
or
git checkout -b fix/issue-you-are-fixing
-
Make your changes following the development guidelines below.
-
Test your changes (see Testing Guidelines)
-
Commit your changes with clear commit messages and sign them (see Signed Commits):
We follow the Conventional Commits specification for commit messages. This provides a standardised format that makes the commit history more readable and enables automated tools for versioning and changelog generation.
The commit message should be structured as follows:
Subject:
<type>(<scope>): <short summary>
│ │ │
│ │ └─⫸ Summary in present tense. Not capitalized. No period at the end.
│ │
│ └─⫸ Commit Scope: "ruleset" for changes to linting rules or should be omitted otherwise
│
└─⫸ Commit Type: build|docs|feat|fix|perf|refactor|revert|test
Body:
<detailed description of changes made in the commit> (wrap at 72 characters)
Footer:
<any additional information, such as references or issue numbers>
| Type | Description | SemVer Impact |
|---|---|---|
build |
A change to CI configuration files and scripts, or that affect the build system or external dependencies | None (unless functionality is affected) |
docs |
Documentation only changes | None |
feat |
A new feature | MINOR (x.Y.z) |
fix |
A bug fix | PATCH (x.y.Z) |
perf |
A code change that improves performance | PATCH (x.y.Z) |
refactor |
A code change that improve code quality but have no functional effect | None (unless functionality is affected) |
revert |
Reverts a previous commit | Depends on the reverted change |
test |
Adding or correcting tests | None |
Note
A commit that has a footer BREAKING CHANGE:, or appends a ! after the type/scope, introduces a breaking API change (correlating with MAJOR in Semantic Versioning). A BREAKING CHANGE can be part of commits of any type.
git commit -m "feat(scope): add rate limiting recommendations"or with more details:
git commit -m "fix(scope): correct validation for API versioning
Resolves issue #123"-
Update your branch/fork with the latest from upstream:
If you are an external contributor, you will need to add the upstream repository as a remote, see fork the repository for more details.
Make sure to keep your fork up to date with the main repository by syncing your fork with the upstream repository.
If you are a member of the
ukhsa-collaborationGitHub organisation, you can update your branch with the latest frommainwith the following commands:git fetch git rebase origin/main
[!NOTE] This repository maintains a linear commit history.
Always use
rebaseinstead ofmergewhen keeping your branch up to date with themainbranch. -
link PR to issue if you are solving one.
-
Push your changes to your branch/fork:
If its your first push to the branch you can use:
git push -u origin your-branch-name
or if you have already pushed to the branch you can use:
git push origin your-branch-name
If you've previously pushed your branch and have rebased, you may need to force push:
git push --force-with-lease origin your-branch-name
-
Create a Pull Request from your branch/fork to the main repository
if you are a member of the
ukhsa-collaborationGitHub organisation, you can create a pull request directly from your branch.If you are an external contributor, you can create a pull request from your fork to the main repository.
-
Fill in the PR template with all relevant information
-
Request a review from maintainers
-
Address any feedback provided during the review process. When making changes to address feedback:
- Make additional commits while the PR is under review
- Once approved, consider squashing related commits for a cleaner history
- Use descriptive commit messages that explain the changes
-
Prepare for merge: Before your PR is merged, make sure your branch is up to date with the latest changes from the
mainbranch.You should be able to do this from the GitHub UI or from the command line.
If you are an external contributor, you can use the following commands to keep your branch up to date with the
mainbranch:# from your feature branch git fetch upstream git rebase upstream/mainIf you are a member of the
ukhsa-collaborationGitHub organisation, you can use the following commands to keep your branch up to date with themainbranch:# from your feature branch git fetch git rebase origin/mainOccasionally you may also be asked to squash your commits to maintain a clean project history. If you are an external contributor, you can use the following commands to squash your commits:
# Squash multiple commits into one git rebase -i HEAD~{number of commits to squash} # and follow the instructions in the editor to squash your commits # or squash all commits since branching from main git fetch upstream git rebase -i upstream/main
If you are a member of the
ukhsa-collaborationGitHub organisation, you can use the following commands to squash your commits:# Squash multiple commits into one git rebase -i HEAD~{number of commits to squash} # and follow the instructions in the editor to squash your commits # or squash all commits since branching from main git fetch git rebase -i origin/main
[!NOTE] This repository maintains a linear commit history.
Always use
rebaseinstead ofmergewhen keeping your branch up to date with themainbranch (see previous step). -
Merge the PR: Once approved and all status checks have passed, including the branch being up to date with main, you can trigger a
fast-forwardmerge by adding thefast-forwardlabel to the pull request. This will initiate an automated, permission-checkedfast-forwardmerge process. Only users withwriteoradminpermissions on the repository can trigger this action. If you're an external contributor, a maintainer may need to do this for you, as the automated process only responds to this tag when it has been added by an authorised user.The merge process is handled by our two-phase GitHub Actions workflow:
- Phase 1: Checks your permissions and PR status when you add the
fast-forwardlabel. - Phase 2: If you have sufficient permissions and the PR is mergeable, the workflow will perform a true
fast-forwardmerge and post the result as a comment on the PR.
If you do not have permission, the workflow will notify you and request you contact a member of the API Standards Team.
Information on why we use a non-standard GitHub merge process can be found in the
fast-forward-pr-merge-init.mddocumentation. - Phase 1: Checks your permissions and PR status when you add the
-
Congratulations! 🎉🎉 You've successfully contributed to the UKHSA API Guidelines, any documentation changes will be automatically deployed to the UKHSA Organisation standards site.
- Write in clear, concise language suitable for technical audiences.
- Use RFC2119 keywords (MUST, SHOULD, MAY, etc.) correctly to indicate requirement levels.
- Include practical examples where appropriate.
- Follow Markdown best practices for formatting.
- Place documentation in the appropriate section of the
/docs/directory. - Preview changes locally using
npm startbefore submitting.
Vacuum is the supported CLI for running the UKHSA ruleset. Rules are authored in the ruleset format that Vacuum consumes.
-
For rule syntax and guidance, see Custom Rulesets.
-
UKHSA specific rules are defined in the
ukhsa.oas.rules.ymlfile. -
Rules should be clearly categorised as MUST, MUST NOT, SHOULD, SHOULD NOT, MAY, MAY NOT and matched against the appropriate severity level.
Rule Category Severity Level MUST errorMUST NOT errorSHOULD warnSHOULD NOT warnMAY infoorhintMAY NOT infoorhint -
Each rule should have a corresponding documentation file in the relevant folder
/docs/linting-rules/must/,/docs/linting-rules/should/or/docs/linting-rules/may/. -
Every rule definition MUST set
documentationUrlso Vacuum outputs can surface a deep link to the matching documentation page (for examplehttps://ukhsa-collaboration.github.io/standards-org/api-design-guidelines/linting-rules/must/<rule-name>/). -
Include references to the relevant sections of the API guidelines.
-
Test the rules that you have created or modified.
-
For information on how to use these rules with your API project, check the How to use the rules documentation section.
-
Test new rules against the example specifications in the
/example/directory (you may need to modify the example definition to test your rules). Vacuum auto-discovers./vacuum.conf.yamlfrom the working directory.vacuum lint example/example.1.0.0.oas.yml
-
Verify that rules produce the expected results for both valid and invalid API definitions.
-
Add automated tests for each new rule:
- Define the rule in
ukhsa.oas.rules.yml. - Create a Jest test file in:
src/__tests__/rules/<rule-name>.test.ts - Use the Vacuum test helper to run the rule against inline specs:
import testRule from '../__helpers__/vacuum-helper.js'; testRule('<rule-name>', [ { name: 'passes when condition is met', document: ` openapi: 3.0.0 info: title: My API version: 1.0.0 paths: {} `, errors: [], }, { name: 'fails when condition is not met', document: ` openapi: 3.0.0 info: title: Bad API version: 1.0.0 paths: {} `, errors: [{ code: '<rule-name>' }], }, ]);
- Define the rule in
-
Run the rule tests:
npm run test -
For documentation, serve the site locally (see Viewing the Guidelines Locally)
The documentation is organised into various markdown files under the docs/ directory. You can navigate and edit these files directly. To preview the documentation as it will appear on the website:
npm run startThis uses docker to host your docs under the hood. After running this script you can view your docs by going to http://localhost:8080/api-design-guidelines/.
While this script is running it will notice when files change and update them so you can see how they look live.
The documentation is continuously deployed from the main branch by GitHub Actions, using the workflow defined in /.github/workflows/publish-guidelines.yml which will trigger a deployment of the main standards-org repository
When documentation changes are merged into the main branch, the documentation site is automatically updated and re-published on GitHub Pages.
When updating rules, follow these steps to ensure proper release and distribution:
- Update the version number in
package.jsonfollowing Semantic Versioning principles:MAJORversion for incompatible changesMINORversion for added functionality in a backwards compatible mannerPATCHversion for backwards compatible bug fixes
- Document all changes in a
CHANGELOG.mdfile, including:- New rules added
- Existing rules modified
- Rules deprecated or removed
- Bug fixes
- Trigger the
/.github/workflows/publish-rules.ymlworkflow to create a release using GitHub Actions. - Add detailed release notes.
- Tag the release with the version number.
Note
Only maintainers with the appropriate permissions can publish new releases of the ruleset npm package.
Thank you for contributing to improving API design and development practices across the UKHSA!