Welcome, and thank you for considering to contribute to ROSA.
For internal Red Hat contributors: post your PR link and Jira story in #forum-rosa-service-engineering and ping @rosa-cli-tf-devs on Red Hat Slack.
The ROSA CLI is the design source of truth for all downstream projects (terraform-provider-rhcs, terraform-rhcs-rosa-classic, terraform-rhcs-rosa-hcp). New features and API changes should land here first.
Repo-local agent guidance lives in AGENTS.md.
Tool-specific entrypoints such as CLAUDE.md and GEMINI.md point back there so the repository only maintains one central guidance file for agents.
CONTRIBUTING.md is the authoritative source for contributor workflow, hooks, verification commands, commit format, and PR expectations.
To contribute bug fixes or features to ROSA:
- Communicate your intent.
- BEFORE YOUR FIRST COMMIT IN A NEW CLONE, YOU MUST RUN
make install-hooks. - Make your changes.
- Test your changes.
- Run
make fmtto align with the project formatting. - Open a Pull Request (PR).
Communicate your intent in the form of a JIRA ticket for ROSA CLI work. Commit messages and PR references in this
repository support both OCM-XXXXX and ROSAENG-XXXX ticket formats. To ensure it is picked up by the ROSA team,
please set component = rosa in the ticket. All JIRA's are refined by the team on a weekly cadence.
Be sure to practice good git commit hygiene as you make your changes. All but the smallest changes should be broken up
into a few commits that tell a story. Use your git commits to provide context for the folks who will review PRs. We strive
to follow conventional commits.
In this repository, the conventional-commit type still lives inside the required OCM-XXXXX | <type>: <message> or
ROSAENG-XXXX | <type>: <message> subject format described below.
REQUIRED BEFORE YOUR FIRST COMMIT IN A CLONE:
make install-hooksYOU MUST LET THE LOCAL HOOKS RUN ON EVERY COMMIT AND PUSH. DO NOT BYPASS LOCAL HOOKS.
The hooks perform:
pre-commit: formats staged Go files (imports + gofmt) and blocks the commit if files were rewritten so you can review/stage updatescommit-msg: validates the commit message formatpre-push: runs format-check, build, lint, changed-files coverage, and unit/integration testspre-pushruns against committed content and blocks when staged/unstaged tracked changes are present- Prow re-runs these checks as required presubmits, so merges are blocked until they pass
- check runs are fail-fast: execution stops at the first failing step
- if you hit any bumps when committing, please let us know
Use this aggregated command before pushing:
make basic-checks # format + format-check + build + lint + changed-files coverage + unit/integration testsbasic-checks forces fresh test execution (no Go test cache) for test steps.
Coverage in these check flows evaluates changed Go files only and requires a minimum of 80% of executable changed lines.
Changed-files coverage uses github.com/vearutop/gocovdiff@v1.4.2 via go run; if it is not already in your Go module cache, Go fetches it automatically.
Use these stage-specific commands when you want to run what each hook runs:
make pre-commit-checks
make pre-push-checksUse these commands for individual checks:
make fmt-check
make rosa
make lint
make coverage-changed-files
make test
make govulncheckmake govulncheck scans the module for known Go vulnerabilities using the pinned
govulncheck tool. It runs two passes:
- Source mode (
./...) for reachable dependency CVEs in the codebase (including tests). - Binary mode (
./rosa) for stdlib/toolchain CVEs in the compiled CLI artifact.
The check is enforced by the optional Prow presubmit govulncheck and is not part of
pre-push-checks. It complements the optional Snyk security presubmit.
When a vulnerability has no fix available, or a fix cannot be adopted yet (for example
a stdlib fix that requires a newer Go toolchain), add an entry to .govulncheck-ignore.yaml
with the GO ID, exact module path, and reason. Remove entries once the fix is adopted.
The ignore wrapper requires jq to parse govulncheck JSON output. The OCP builder image
used by ROSA Prow jobs (container: from: src) does not include jq; make govulncheck
downloads a static jq binary (currently pinned in hack/govulncheck.sh, monitored by
Renovate) into a private mktemp directory when it is not already on PATH, and verifies the
download against the upstream sha256sum.txt for that release. For local runs, install jq
or rely on that bootstrap. yq is optional; the wrapper falls back to awk when yq is not
installed.
Commit message checks are performed by the commit-msg hook during commits.
Formatting helpers:
make fmt # formats all Go files under cmd/, pkg/, tests/ and fails if rewrites were needed
make fmt-staged # formats only staged Go files and fails if rewrites were needed (used by pre-commit hook)
make fmt-check # verifies formatting without rewriting filesIf you want to inspect planned execution without running checks:
make run-checks -- pre-push --list-steps
make run-checks -- pre-push --dry-run
make run-checks -- basic --list-steps
make run-checks -- basic --dry-runHook scripts are internal and should not be run manually.
The commit message should follow this template:
(OCM-XXXXX or ROSAENG-XXXX) | <type>[optional scope][!]: <description>
[optional BODY]
[optional FOOTER(s)]For example:
OCM-6141 | feat: Allow longer cluster names up to 54 chars
Also allow users to supply an optional domain-prefix to customize the DNS
Signed-off-by: Foo Bar <foo.bar@baz.com>ROSAENG-6531 | fix: support ROSAENG ticket prefixes in commit validationThe commit contains the following structural types, to communicate your intent:
fix:a commit of the type fix patches a bug in your codebase (this correlates with PATCH in Semantic Versioning).feat:a commit of the type feat introduces a new feature to the codebase (this correlates with MINOR in Semantic Versioning).
Types other than fix: and feat: are allowed:
build: Changes that affect the build system or external dependenciesci: Changes to our CI configuration files and scriptsdocs: Documentation only changesperf: A code change that improves performancerefactor: A code change that neither fixes a bug nor adds a featurestyle: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)test: Adding missing tests or correcting existing tests
[!IMPORTANT] DCO Sign-off Required: Every commit must include a Developer Certificate of Origin (DCO) sign-off line (Signed-off-by: Name ). Use git commit -s when committing.
The changelog is automatically generated using git-cliff
configured via cliff.toml. Only the CHANGELOG.md in the default branch
contains the complete changelog history.
Workflow:
- Push a stable release tag (
vX.Y.Z) to trigger the automation. - GitHub Actions automatically generates the changelog from the previous release tag.
- A PR is created to
masterwith the new changelog entry, labeledchangelogto be reviewed. - A human reviews and merges that PR.
The changelog follows the existing format with sections for FEATURES, ENHANCEMENTS (with Bug fixes, Documentation, and Chores subsections), and other categories. Commits are automatically grouped based on their conventional commit type.
Contributors do not add changelog fragments to feature PRs.
To regenerate the entire historical changelog from all stable tags:
make changelog-bootstrapTo generate or update the entry for a specific stable tag:
make changelog-generate TAG=v1.2.63The helper script auto-installs a pinned git-cliff binary when git-cliff is
not already available locally.
If the automated PR misses a release window, the historical changelog can be
backfilled manually by regenerating the entry for that stable tag and opening a
normal PR with the updated CHANGELOG.md.
All code should be covered by tests. We use Ginkgo. Other third party testing package will be rejected.
Once you made and tested your changes, create a pull request (PR). In the PR overview please link the
jira ticket associated with your change. This should follow the format JIRA: OCM-XXXX or JIRA: ROSAENG-XXXX. Note the key word JIRA,
use of any other key word may result in the bot performing unwanted action to the ticket in JIRA. Please also include in the
overview any additional information not in the JIRA that may help set context around your intent. Also include any extra
validation steps which may help reviews to validate the changes.
We work on a Sprint basis, all changes should be tracked by a JIRA. When being worked on these changes should be added to
the current SDA sprint. These sprints are denoted as SDA - Sprint xxx. The workflow should be as follows:
Todowill complete in this current sprintIn Progressticket is currently being worked onCode ReviewPR has been created and is being reviewed by the team.ReviewOnce the changes have been merged, move ticket toReviewa QE person will be assigned to the ticket and tested.DoneOnce QE are satisfied with the change and bugs have been fixed the QE person assigned to your ticket will mark it as done
During Review, remain assigned to the ticket, so that QE knows who to assign any follow-up bugs to during testing. You
will also be asked to review test cases for this change. QE will supply you with a link to the test cases, if you approve
the test cases add tc-approved label to the JIRA, if you need changes to the test cases work with QE in the JIRA comments
to resolve these changes.
This repository is using Prow CI running at https://prow.ci.openshift.org/, configured in https://github.com/openshift/release repo.
.golangciversion file is read by the lint job commands there:
https://github.com/openshift/release/blob/master/ci-operator/config/openshift/rosa/openshift-rosa-master.yaml
The govulncheck presubmit runs make govulncheck and is optional while the check is
being rolled out. Trigger it manually with /test govulncheck.
We automatically test the structure of the ROSA CLI to ensure commands and command flags are not accidentally added or removed. When you first create a new command, the test suite will fail because of this.
You need to add your command to the following file command_structure in the correct location within the command tree in order for this test to pass.
You additionally need to create a directory under the command_args sub-directory
and create a file called command_args.yml. This file should contain a simple yaml list of the flags supported by your command.
For example, a command with flag foo, bar, bob would have the following command_args.yml:
- name: foo
- name: bar
- name: bobIf you are contributing code, please ensure that you are handling errors properly. You should
not call os.Exit() in your Command (there is a significant amount of this in our code which we
are working to remove)
Please use Run: run instead of RunE: runE when writing commands,
in order to stop the usage info being printed when an error is returned.
In some cases new features have minimal OCP versions.
To add validation for a minimal version, please add the minimal version
const to features.go and use the IsFeatureSupported function.
If you have any questions about the code or how to contribute, don't hesitate to open an issue in this repo