Open-Source Wikis

/

MinIO

/

How to contribute

/

Development workflow

minio/minio

Development workflow

A typical inner loop for a MinIO contributor.

Set up

git clone https://github.com/minio/minio
cd minio
git remote add upstream https://github.com/minio/minio
go install ./...

go install ./... will fetch every dependency listed in go.mod (Go 1.24+ required) and produce a minio binary in $GOPATH/bin. Use make build to put it in the repo root with version-stamped LDFLAGS instead.

Branch

git checkout -b my-change upstream/master

The project does not use long-lived feature branches. Every change is a fork-branch → PR → squash-merge to master.

Make changes

Three layers of work, each with its own etiquette:

Touching cmd/

Most server logic lives here. Conventions:

  • HTTP handler signatures match func (h objectAPIHandlers) MyVerbHandler(w http.ResponseWriter, r *http.Request). Look at neighbours in the same file for response writing helpers (writeSuccessResponseXML, writeErrorResponse, writeErrorResponseHeadersOnly).
  • New error codes go into cmd/api-errors.go and the matching string table is regenerated via go generate.
  • Handlers acquire and release locks with objectAPI.NewNSLock(...) from cmd/namespace-lock.go. Holding a lock across a long network call is a known foot-gun.

Touching internal/

internal/ is for reusable, dependency-light modules. Anything you put there must compile without pulling in cmd/.

  • New configurable settings live in internal/config/<area>/. Each area registers its HelpKVS and Config types with internal/config/config.go.
  • New event/notification targets go into internal/event/target/ and follow the existing Save/Send/Close interface.
  • New KMS providers go into internal/kms/ (the active integrations are KES via aead.dev/mtls and the local-key fallback).

Touching tests and docs

  • Unit test files sit next to the file they test (foo.gofoo_test.go).
  • Integration scripts live in docs/<feature>/ and are referenced from Makefile. They run real minio binaries and use mc.

Lint, format, generate

Before pushing:

make verifiers

This runs:

  • go generate ./... and fails if any _gen.go differs.
  • go mod tidy and fails if go.sum differs.
  • golangci-lint run --build-tags kqueue --timeout=10m --config ./.golangci.yml.
  • typos ./ if the typos binary is on PATH (.typos.toml controls allowlists).

If _gen.go files are dirty after go generate, commit them. They are produced by github.com/tinylib/msgp and golang.org/x/tools/cmd/stringer (both declared in the tool block of go.mod).

Test

make test          # unit tests
make test-race     # race-instrumented unit tests
make test-replication
make verify-healing

See Testing for what each of those does and which scripts they call.

Build

make build         # ./minio
make install       # $GOPATH/bin/minio
make install-race  # race-instrumented binary in $GOPATH/bin/minio

For multi-arch:

env GOOS=linux GOARCH=arm64 go build

Commit

git add -A
git commit -m "concise subject line

Longer explanation of why the change was needed and what it
does. Wrap at 72 chars. Reference the related issue if there is one."

Squash multiple WIP commits with git rebase -i before pushing.

Push and PR

git push origin my-change

Open the PR on GitHub against minio/minio:master. The .github/workflows/ pipelines run verifiers, build, and the integration suites. Merges happen by squash.

After merge

  • The PR title becomes the squash commit subject. The team re-uses commit subjects in release notes; aim for "Add X", "Fix Y", "Refactor Z" style.
  • Releases are cut by tag. The release machinery is in Makefile (hotfix, hotfix-push, release targets) and buildscripts/gen-ldflags.go.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Development workflow – MinIO wiki | Factory