# Development

This page details the process for getting up and running locally for OPA development. If you're a first time contributor, we recommend you read through the [Contributing to OPA](/docs/contrib-code) page first.

OPA is written in the [Go](https://go.dev/) programming language. If you are new to Go, consider reading [Effective Go](https://go.dev/doc/effective_go), [Go Code Review Comments](https://go.dev/wiki/CodeReviewComments) or [How to Write Go Code](https://go.dev/doc/code) for guidance on writing idiomatic Go code.

Requirements:

*   Git
*   GitHub account (if you are contributing)
*   Go (please see the project's [go.mod](https://github.com/open-policy-agent/opa/blob/main/go.mod) file for the current version in use)
*   GNU Make
*   A POSIX-compatible shell (`bash`)
*   A C compiler (e.g., `gcc`) for CGO
*   Python3, pip, `yamllint` (if linting YAML files manually)

## Windows

The build system relies on `bash` shell scripts and GNU Make, which are not available out of the box on Windows. The recommended approach is to use [WSL (Windows Subsystem for Linux)](https://learn.microsoft.com/en-us/windows/wsl/install), which provides a full Linux environment where the standard requirements above apply.

If you prefer to develop without WSL, you can use [MSYS2](https://www.msys2.org/) with the MinGW64 toolchain, which provides `bash`, `make`, and `gcc`. Note the following when using MSYS2/MinGW64:

*   Install the MinGW64 variants of GCC, Go, and Make (e.g., `pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-go make`).
*   Configure Git to check out files with Unix-style line endings (`git config --global core.autocrlf input`) to avoid test failures caused by `CRLF` vs `LF` differences.
*   A small number of tests may still fail due to Windows path separator differences (`\\` vs `/`). This is expected and should not block development.
*   Some build scripts (e.g., `go:generate` directives in `main.go`) invoke `.sh` files directly. These require `bash` to be in your `PATH`, which MSYS2 provides.

## Getting Started

After forking the repository and creating a [clone from your fork](https://docs.github.com/en/get-started/exploring-projects-on-github/contributing-to-a-project), just run `make`. This will:

*   Build the OPA binary.
*   Run all of the tests.
*   Run all of the static analysis checks.

If the build was successful, a binary will be produced in the top directory (`opa_<OS>_<ARCH>`).

Verify the build was successful with `./opa_<OS>_<ARCH> run`.

You can re-build the project with `make build`, execute all of the tests with `make test`, and execute all of the performance benchmarks with `make perf`.

For quicker development-test iteration, you may use `make test-short` during development, and only run `make test` before submitting your changes. This avoids running the slowest tests and normally completes under a minute (compared to the several minutes required to run the full test suite).

The static analysis checks (e.g., `go fmt`, `golint`, `go vet`) can be run with `make check`.

> To correct any imports or style errors run `make fmt`.

## Workflow

### Fork, clone, create a branch

Go to [https://github.com/open-policy-agent/opa](https://github.com/open-policy-agent/opa) and fork the repository into your account by clicking the "Fork" button.

Clone the fork to your local machine:

```
git clone git@github.com/<GITHUB USERNAME>/opa.git opacd opagit remote add upstream https://github.com/open-policy-agent/opa.git
```

Create a branch for your changes.

```
git checkout -b somefeature
```

### Developing your change

Develop your changes and regularly update your local branch against upstream, for example by rebasing:

```
git fetch upstreamgit rebase upstream/main
```

> Be sure to run `make check` before submitting your pull request. You may need to run `go fmt` on your code to make it comply with standard Go style. For YAML files, you may need to run the `yamllint` tool on the `test/cases/testdata` folder to make sure any new tests are well-formatted. If you have Docker available, you can run `make check-yaml-tests` to run `yamllint` on the tests without installing any Python dependencies.

### Submission

Commit changes and push to your fork.

```
git commit -sgit push origin somefeature
```

> Make sure to use a [good commit message](/docs/contrib-code#commit-messages).

Now, submit a Pull Request from your fork. See the official [GitHub Documentation](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork) for instructions to create the request.

> Hint: You should be prompted to with a "Compare and Pull Request" button that mentions your new branch on [https://github.com/open-policy-agent/opa](https://github.com/open-policy-agent/opa)

Once your Pull Request has been reviewed and signed off please squash your commits. If you have a specific reason to leave multiple commits in the Pull Request, please mention it in the discussion.

> If you are not familiar with squashing commits, see [the following blog post for a good overview](https://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html).

## Benchmarks

Several packages in this repository implement benchmark tests. To execute the benchmarks you can run `make perf` in the top-level directory. We use the Go benchmarking framework for all benchmarks.

## Dependencies

OPA is a Go module [https://github.com/golang/go/wiki/Modules](https://github.com/golang/go/wiki/Modules) and dependencies are tracked with the standard [go.mod](https://github.com/open-policy-agent/opa/blob/main/go.mod) file.

All `go` commands from the [Makefile](https://github.com/open-policy-agent/opa/blob/main/Makefile) will enable module mode by setting `GO111MODULE=on`.

To update a dependency ensure that `GO111MODULE` is either on, or the repository qualifies for `auto` to enable module mode. Then simply use `go get ..` to get the version desired. This should update the [go.mod](https://github.com/open-policy-agent/opa/blob/main/go.mod) and (potentially) [go.sum](https://github.com/open-policy-agent/opa/blob/main/go.sum) files.

Example workflow for updating a dependency:

```
go get -u github.com/sirupsen/logrus@v1.4.2  # Get the specified version of the package.go mod tidy                                  # (Somewhat optional) Prunes removed dependencies.
```

If dependencies have been removed ensure to run `go mod tidy` to clean them up.

### Go

If you need to update the version of Go used to build OPA you must update these files in the root of this repository:

*   `.go-version`\- which is used by the Makefile and CI tooling. Put the exact go version that OPA should use.

## Refactoring and Style Fixes

If you've found some code that you think would benefit from a refactoring — either by making it more readable or more performant, that's great! Some things should however be considered before you submit such a change:

*   Avoid mixing bug fixes and feature PRs with refactorings or style fixes. These PRs are generally difficult to review. Instead, split your work up in multiple, separate PRs. If a refactoring is "needed" for a feature, at least ensure to split the two into separate commits.
*   If you intend to work on a larger refactoring project, make sure to first create an issue for discussion. Sometimes things are the way they are for a reason, even when it's not immediately obvious.
*   Ensure that there are tests covering the code subject to change.

## CI Configuration

OPA uses Github Actions defined in the [.github/workflows](https://github.com/open-policy-agent/opa/tree/main/.github/workflows) directory.

### Github Action Secrets

The following secrets are used by the Github Action workflows:

| Name | Description |
| --- | --- |
| S3\_RELEASE\_BUCKET | AWS S3 Bucket name to upload `edge` release binaries to. Optional -- If not provided the release upload steps are skipped. |
| AWS\_ACCESS\_KEY\_ID | AWS credentials required to upload to the configured `S3_RELEASE_BUCKET`. Optional -- If not provided the release upload steps are skipped. |
| AWS\_SECRET\_ACCESS\_KEY | AWS credentials required to upload to the configured `S3_RELEASE_BUCKET`. Optional -- If not provided the release upload steps are skipped. |
| DOCKER\_IMAGE | Full docker image name (with org) to tag and publish OPA images. Optional -- If not provided the image defaults to `openpolicyagent/opa`. |
| DOCKER\_WASM\_BUILDER\_IMAGE | Full docker image name (with org) to tag and publish WASM builder images. Optional -- If not provided the image defaults to `openpolicyagent/opa-wasm-builder`. |
| DOCKER\_USER | Docker username for uploading release images. Will be used with `docker login`. Optional -- If not provided the image push steps are skipped. |
| DOCKER\_PASSWORD | Docker password or API token for the configured `DOCKER_USER`. Will be used with `docker login`. Optional -- If not provided the image push steps are skipped. |
| SLACK\_NOTIFICATION\_WEBHOOK | Slack webhook for sending notifications. Optional -- If not provided the notification steps are skipped. |
| NETLIFY\_BUILD\_HOOK\_URL | URL to trigger Netlify (openpolicyagent.org) deploys after release. Optional -- If not provided the Netlify steps are skipped. |

### Periodic Workflows

Some of the Github Action workflows are triggered on a schedule, and not included in the post-merge, pull-request, etc actions. These are reserved for time consuming or potentially non-deterministic jobs (race detection tests, fuzzing, etc).

Below is a list of workflows and links to their status:

| Workflow | Description |
| --- | --- |
| [![Nightly](https://github.com/open-policy-agent/opa/workflows/Nightly/badge.svg?branch=main)](https://github.com/open-policy-agent/opa/actions?query=workflow%3A%22Nightly%22) | Runs once per day at 8:00 UTC. |