Contributions to this repository are subject to the Developer Certificate of Origin.
All Documentation content that resides under the docs/ directory of this
repository is licensed under Creative Commons:
CC BY-SA 4.0.
This notice should stay as the first item in the CONTRIBUTING.md file.
Thank you for your interest in contributing to the GitLab CLI! This guide details how to contribute to this extension in a way that is easy for everyone. These are mostly guidelines, not rules. Use your best judgement, and feel free to propose changes to this document in a merge request.
Please do:
- Check existing issues to verify that the bug or feature request has not already been submitted.
- Open an issue if things aren't working as expected.
- Open an issue to propose a significant change.
- Open an issue to propose a feature.
- Open a merge request to fix a bug.
- Open a merge request to fix documentation about a command.
- Open a merge request for an issue and leave a comment claiming it.
Please avoid:
- Opening merge requests for issues marked
blocked. - Opening merge requests for documentation for a new command specifically. Manual pages are auto-generated from source after every release
We want to create a welcoming environment for everyone who is interested in contributing. Visit our Code of Conduct page to learn more about our commitment to an open and welcoming environment.
If you are a GitLab team member that is interested in becoming a maintainer of the CLI, we follow these basic steps described in the handbook:
- Familiarize yourself with the codebase and past reviews.
- When you're ready, add yourself as a reviewer in your team page.
- After the current maintainers feel confident you're ready to be a maintainer, you're added to the project, and can update your team page again.
Create a new issue from the "Default" template and follow the instructions in the template.
Read about the contribution process in development_process.md. This document explains how we review and release changes.
If your merge request is trivial (fixing typos, fixing a bug with 20 lines of code), create a merge request.
If your merge request is large, create an issue first. See Reporting Issues and Proposing Features. In the issue, the project maintainers can help you scope the work and make you more efficient.
GitLab Workspaces are fully enabled for the CLI project, providing a complete development environment in your browser.
Benefits of using Workspaces:
- Zero setup: No requirement to install Go, dependencies, or clone the repository locally.
- Pre-configured environment: All development tools and dependencies are ready to use.
- Immediate development: Start coding, running tests, or making edits right away.
- New contributor onboarding: A great way for new contributors to start without local machine setup.
- MR-based development: Open a Workspace directly from a merge request for testing and reviews.
- No context switching: Make changes during code reviews without switching to your local machine.
For more information see, Creating a workspace.
Prerequisites:
- Go version as defined by
main/go.mod
Build with: make or go build -o bin/glab ./cmd/glab/main.go
Run the new binary as: ./bin/glab
This project supports Lefthook for managing Git hooks. Lefthook helps catch issues before pushing to CI by running checks locally.
-
Install development tools using mise:
# Install mise if you don't have it curl https://mise.run | sh # Install all development tools (includes lefthook) make bootstrap # Enable git hooks lefthook install
This installs all tools defined in
.tool-versions: Go, golangci-lint (includes gofumpt and goimports formatters), shellcheck, markdownlint-cli2, vale, lychee, Node.js, lefthook, and commitlint dependencies.
- pre-commit: Formats and lints Go code (golangci-lint with gofumpt/goimports), lints shell scripts (shellcheck), auto-fixes Markdown formatting (markdownlint), checks and regenerates documentation if command files changed (blocks commit until docs are staged)
- commit-msg: Validates commit messages follow conventional commits format
- pre-push: Runs documentation validation (markdownlint, vale, lychee) on changed files
If a required tool is not installed, the hook will display a warning and skip that check. This means you can install lefthook immediately and add tools incrementally. All validation also runs in CI, so nothing is missed.
If you need to skip hooks temporarily:
# Skip all hooks for one commit
LEFTHOOK=0 git commit -m "message"
# Skip all hooks for one push
LEFTHOOK=0 git push
# Skip specific hook
LEFTHOOK_EXCLUDE=pre-push git pushRun tests with: go test ./... or make test.
There are some integration tests that perform real API requests to https://gitlab.com.
If the environment variables GITLAB_TEST_HOST and GITLAB_TOKEN are not set, the integration tests will fail in CI if
being run in the gitlab-org/cli project. They will be skipped locally or in forks if GITLAB_TEST_HOST and GITLAB_TOKEN
are both are omitted.
Integration tests use the _Integration test suffix and use the _integration_test.go file suffix.
GITLAB_TEST_HOST is set to https://gitlab.com in CI.
GITLAB_TOKEN must be a
personal access token and requires the api scope.
To ensure the glab duo feature is functioning correctly, the token's user must have a GitLab Duo seat.
Create a new issue from the "Feature Request" template and follow the instructions in the template.
The Design Command-Line Tools People Love presentation by Carolyn Van Slyck provides some great guidance on things to consider when implementing a CLI tool. We recommend the entire presentation, but the following points are especially important in the context of the GitLab CLI.
GitLab CLI commands use a noun-first, verb-second grammatical structure, like
glab ci list. Also, these verbs are shared by various commands, and have
expected behavior as a result:
create- Used when creating a singular object. For example,glab mr createcreates a new merge request.list- Used by commands that output more than one object at a time. For example,glab ci listreturns a list of all running pipelines.get- Used by commands that output a singular object at a time. For example,glab ci get --pipeline-id 1returns the pipeline with the specified ID.update- Used by commands that update one object at a time. For example,glab mr update 1 --title "new title"updates the title of the merge request with ID1.delete- Used when deleting one or more objects at time. For example,glab ci delete 1,2,3deletes the pipelines with IDs1,2, and3.
Features generally have some or all of these commands. However, some features do not map well to the listed commands. In situations like these, it's okay to create or use separate verbs that make the most sense for the feature.
Commands in this repository follow the OpenShift guidelines with the following differences:
xxxOptionsstructs are private. No need to export them.xxxOptionsstructs are called justoptionsto avoid repeating the package name.- Methods and fields on
optionsare not exported. - Only implement the necessary methods out of
complete,validateandrun. - Options struct constructor is optional and should be named
newOptions- unexported and does not repeat the package name.
When designing a feature, consider the existing ecosystem. It may be helpful to ask, "What's the most popular CLI tool in this domain?". The answer can help you decide the terminology used, a preference for a flag instead of a positional argument, and many more things. For example:
- When working on a Kubernetes-related feature,
kubectldesign patterns might play a big role designing feature's command set. - When working on GitLab-specific features, use the current documentation and command list for design patterns.
Considering the context of use helps create a unifying experience that feels natural to users who work with other tooling in the same domain space.
Design with human readable output as the default. The
go-humanize module helps transform
various types into a human-friendly version. See the module's documentation for
a complete listing of the transformations supported.
- Create a new branch:
git checkout -b my-branch-name - Make your change, add tests, and ensure tests pass
- Submit a merge request
We use golangci-lint to lint and format
the code in this project. The linter configuration can be seen in the
.golangci.yml file for this project.
Additional details about code style and format are in the go guide.
Each commit message consists of a header, a body, and a footer. The header has a special format that includes a type, a scope, and a description:
<type>(<scope>): <description>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
Each line in the commit message should be no longer than 72 characters.
The message header is mandatory, and should be a single line that contains a succinct description of the change containing a type, an optional scope, and a description. Ideally, it should not be more than 50 characters in length.
Following these conventions results in a clear changelog for every version.
It's generally a good idea to follow the conventions for your MR's title as well as for commit messages. This way, if your merge request is squashed upon merge, the maintainer can use its title as the final commit message, creating a properly-formatted history.
If your MR contains multiple commits but only one logical change, the Squash commits when merge request is accepted option (enabled by default in this project) will allow GitLab to use the MR title as the commit message.
This describes the kind of change that this commit is providing
- feat: A new feature (adding a new component, providing new variants for an existing component, etc.).
- fix: A bug fix (correcting a styling issue, addressing a bug in a component's API, etc.).
When updating non-dev dependencies, mark your changes with the
fix:type. - docs: Documentation-only changes.
- style: Changes that do not affect the meaning of the code
(whitespace, formatting, missing semicolons, etc). Not to be used for UI changes as those are
meaningful changes, consider using
feat:offix:instead. - refactor: A code change that neither fixes a bug nor adds a feature.
- perf: A code change that improves performance.
- test: Adding missing tests or correcting existing tests.
- build: Changes that affect the build system.
- ci: Changes to our CI/CD configuration files and scripts.
- chore: Other changes that don't modify source or test files. Use this type when adding or updating dev dependencies.
- revert: Reverts a previous commit.
Each commit type can have an optional scope to specify the place of the commit change: type(scope):. It is up to you to add or omit a commit's scope. When a commit affects a specific component, use the component's PascalCase name as the commit's scope. For example:
feat(statusbar): automatically switch pipelines
Scope can be anything specifying the place of the commit change. For example events, kafka, userModel, authorization, authentication, loginPage, etc
This is a very short description of the change
use imperative, present tense: “change” not “changed” nor “changes”don't capitalize the first letterno dot (.) at the end
Just as in the description, use imperative, present tense: “change” not “changed” nor “changes.” Include motivation for the change and contrast it with previous behavior.
Finished, fixed or delivered stories should be listed on a separate line in the footer prefixed with "Finishes", "Fixes" , or "Delivers" keyword like this:
[(Finishes|Fixes|Delivers) #ISSUE_ID]
feat(kafka): implement exactly once delivery
- ensure every event published to kafka is delivered exactly once
- implement error handling for failed delivery
Delivers #065fix(login): allow provided user preferences to override default preferences
- This allows the preferences associated with a user account to
override and customize the default app preferences like theme or timezone.
Fixes #025We use the following logic to lint your MR's commit messages:
graph TD
A{Are there multiple commits?} --no--> B[Commit must be valid]
A --yes--> C
C{Is MR set to be squashed?} --no--> D[Every commit must be valid]
C --yes--> E[MR title must be valid]
To create a workspace:
- Go to the CLI project or any merge request.
- In the upper-right corner, select Code.
- Select Open in Workspace.
- Complete the form. The form is pre-filled with cluster agent configuration, project reference, and Devfile.
- Select Create workspace.
Wait until the workspace status is Running, then select Open workspace to launch your development environment.
After your workspace is running, you can start developing:
# Build the CLI binary
make
# Run the CLI
./bin/glab
# Run unit tests
make test
# Format and lint code
make lintFor workspace-specific issues:
- See the GitLab Workspaces documentation.
- Reach out in the Slack
#f_workspaceschannel. - Create an issue in the Workspace User Feedback Epic.
The project includes a .vscode/launch.json file that you can use in Visual Studio Code when debugging the code.
Add the command line arguments in the args array otherwise you will see the default --help output.
Make sure you don't commit this file when pushing your changes.