Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Process

Anyone can hack on Hammerhead - if you want to see something implemented, get stuck in! Hammerhead is built with maintainability at the forefront of its design decisions, meaning that almost all the codebase is easy to read, understand, and intuitive to build on. You don’t need to have a decade’s experience with Golang to get something done.

In order to contribute, all you need is a code editor (JetBrains’ Goland is recommended, but Visual Studio Code with the Go extension will work fine too). You will also need git, and obviously, the latest version of Go. You will also want to have an account on Codeberg, so that you can open a pull request with your changes.

Setting up the development environment

First off, you’re going to want to acquire a copy of the Hammerhead source code. You can clone the repo however you want, however your code editor will usually have a UI option for it somewhere. Make sure you clone the HTTPS url, https://codeberg.org/timedout/hammerhead.git - cloning the SSH URL will likely give you a “forbidden” error, unless you have push access to the repository (in which case you won’t need this guide).

Tip

Codeberg can be unreliable at times, so it’s recommended you include a mirror as a secondary remote. You can do this with the below command:

#git remote add <mirror-name> <mirror-url>
git remote add nexy-forge https://git.nexy7574.co.uk/nex/hammerhead.git

Then, if Codeberg is ever unreachable, you can pull missed changes from an up-to-date mirror instead.

Do not submit issues or pull requests to mirrors - if the primary repository is unavailable, please either wait until it returns, or coordinate sharing patches with maintainers in the Matrix room.

You’ll then want to make sure you can install all the dependencies required for devel. You can do this with go mod download. This may take a while, as Hammerhead has a complex dependency tree.

Finally, to make sure you’ll be able to test your changes, run the build script with ./build.sh. Resolve any errors you encounter, or reach out for help if you can’t.

Now you’re all set to start making changes!

Pre-commit

You will want to install one of either pre-commit or prek in order to run some pre-commit hooks. These hooks will run when you run git commit (or use the associated functions in your IDE), and ensure that you don’t push code that looks/behaves badly or that fails unit tests.

Use either pre-commit install or prek install to install the hooks, and run pre-commit run -a or prek -a to run the hooks manually (otherwise they’ll be run before commit, as the name implies).

If you don’t use these hooks, CI/CD may fail on your pull request, meaning it won’t be eligible for merge.

Making your changes

First of all, you’re going to want to fork Hammerhead into your own repository, so that you can push your changes before opening a pull request. You will want to add this as a remote too, such as git remote add fork ssh://git@codeberg.org/myusername/hammerhead (you can also use HTTPS, but SSH is easier if you have MFA enabled).

Then, before you make any changes, you’ll want to switch to your own branch. Working on main will only introduce merge conflicts, and your pull request will be rejected if you try to merge your main into the upstream main. The recommended branch names are myhandle/scope/name:

  • myhandle should be your Codeberg username (but can be any handle that is unique and ideally identifiable to you).
  • scope should be one of the conventional commit scopes (such as fix, feat, docs, style, perf).
  • name should be a short, sensible self-explanatory name, such as support-msc1234.

This naming convention will allow you to avoid branch/namespace conflicts and makes it easier to find related branches later down the line.

Create a new branch from main like so: git checkout -b myhandle/scope/name origin/main.

Then, when pushing, git push -u <remote> myhandle/scope/name. You can omit all those arguments for subsequent pushes, simply git push. remote will probably be fork, as per the previous example.

Make sure that you test your changes as you go. Ideally, write unit tests to prevent regressions in the future (although this isn’t mandatory). While WIP PRs are acceptable, please don’t open PRs that aren’t near completion, or that you don’t plan on maintaining. Realistically you should only have one or two PRs awaiting review at a time, otherwise you may overburden yourself.

Also: try to break what you write. Don’t just test the best-case scenario, throw some absurd situations and inputs at it and ensure that it doesn’t behave unexpectedly. If you don’t try to break it, somebody else (potentially with less wholesome goals) will.

Documentation

Most of the time, if you’re changing something user-facing, you will need to update the documentation. For example, updating the configuration (in any form) will require changing the configuration reference documentation at the very least.

Hammerhead’s documentation uses [mdbook] (install), and compiles a bundle of Markdown (ref) files into HTML.

You can live preview your changes with mdbook serve and visiting https://localhost:3000.

When you submit a pull request that modifies anything under the docs/ directory, the Deploy documentation CD workflow will run. When running against a pull request, this workflow does not deploy the documentation anywhere (that only happens for commits to dev), but will produce an artefact containing the built documentation. You can download that artefact and unzip it to see the generated content, should you wish. Hosting documentation previews is planned.

Submitting your changes

Once you’re happy with your work, make sure you’ve pushed it to your fork, and head on over to https://codeberg.org/timedout/hammerhead/pulls. Navigate to “New pull request” in the top right, and out of the two drop-down boxes presented under the title, select the right-hand one, and plug in your branch’s name (you may have to hunt for it).

You should get the chance to preview the diff that will be presented to reviewers before continuing. Make sure that it looks like the changes you expect it to, and then activate “new pull request”.

The pull request title should be short (<50 words) and explains what your pull request does at a glance. If you cannot fit the title in under 50 or so words, chances are your scope is too large, and your pull request should be broken down in to several, smaller pull requests.

In the pull request’s description, describe the changes you made in more detail, including what you changed and why you decided to change it. If possible, also link to any open issues that relate to your pull request, and include any other context that will help others in the future determine why you made any changes.

Once happy, hit “create pull request”. The Matrix room will be notified that you have opened a pull request, so sit back and relax - a maintainer will triage and review your pull request when they get time.

Tip

Maintainers may wish to slightly tweak your pull request before merging it, typically to fix minor issues or rectify code style problems. While allowing maintainer edits is enabled by default, you have the option to turn it off. It is advised you leave it enabled if you would like your pull request to be merged faster.

On the contrary, please don’t expect maintainers to do your PR for you. If changes are requested, it is your responsibility to act on that request. PRs that go untouched for a long time may be closed due to inactivity at the maintainers’ discretion.

How will my PR be merged?

If your pull request receives an approval, it will likely be merged shortly after. If CI is still running/pending, the PR will be set to auto-merge once that process completes.

Merges in Hammerhead are typically done via rebase + fast-forward, since this retains the exact commit order specified in the pull request, which makes it easier to track down previous changes atomically. However, pull requests that have a lot of commits, or poor commit messages, will instead be squashed. Squashes lose the history and some metadata, but allow your PR to be merged into the main branch in one single, monolithic commit instead (you still get attribution). In some special cases, a maintainer may manually merge your pull request. How that happens is situation-dependent.

If you want your pull request to be merged in a specific way, please denote that in your pull request description. The only merge method that is forbidden is merge commits.

What are all these checks?

When you open a pull request, you may notice a few checks (also referred to as workflows, CI/CD, jobs) are pending. If you have had a pull request of yours merged before, these will likely start running straight away (assuming there’s an available runner). Otherwise, you will need to wait for a maintainer to hit approve, which typically happens after triage and after a maintainer has made sure you haven’t requested malicious changes.

If you made changes to anything under the cmd/ or pkg/ directories, the “build” checks will be invoked. These checks involve compiling, testing, and linting your changes to make sure that they are functional and roughly meet the code quality standards. Unless otherwise stated, these checks must pass in order for your PR to be eligible for merge. The Build / binaries check will also produce AMD64 and ARM64 binaries as artefacts upon success - you can download these (zipped) by clicking on “Details”.

If you made changes to the docs/ directory, the “deploy” checks will be invoked. These checks will handle incoming documentation changes for you. Deploy / docs specifically will also produce an artefact containing the built documentation (again, zipped) for the associated commit. See also: Documentation.

Conclusion

If you have any questions not answered in this document, please ask them in our Matrix room!