Skip to content

Commit

Permalink
*: automate releases with goreleaser (operator-framework#4034)
Browse files Browse the repository at this point in the history
This commit adds tooling for automated releases in CI using goreleaser, 
agnostic of CI platform (albeit with some environment configuration).
Any Github user with write capabilities to the SDK repo can start
a release.

.ci/gpg: GPG public key, encrypted private subkey (used for signing),
and script to decrypt private subkey in CI

website/scripts: scripts to update versions in release commits and
branches at build time

.goreleaser.yml: goreleaser config file

*: script and Makefile updates to support automated releases

docs: release and installation guide simplifications, related docs cleanup
  • Loading branch information
Eric Stroczynski authored Nov 30, 2020
1 parent 74f5a36 commit 7e490b4
Show file tree
Hide file tree
Showing 22 changed files with 579 additions and 534 deletions.
33 changes: 33 additions & 0 deletions .ci/gpg/create-keyring.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/bin/bash

DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"

# Modified from https://blogs.itemis.com/en/secure-your-travis-ci-releases-part-2-signature-with-openpgp

function err_exit() {
echo "ERROR: ${1:-"Unknown Error"} Exiting." 1>&2
exit 1
}

declare -r GPG_HOME="${DIR}/keyring"
declare -r SECRING_AUTO="${GPG_HOME}/secring.auto"
declare -r PUBRING_AUTO="${GPG_HOME}/pubring.auto"

mkdir -p "$GPG_HOME"
cp "${DIR}"/*.auto* "${GPG_HOME}"

echo -e "\nDecrypting secret key..."
{
# $GPG_PASSWORD is taken from the script's env (injected by Travis CI).
echo $GPG_PASSWORD | gpg --decrypt \
--pinentry-mode loopback --batch \
--passphrase-fd 0 \
--output "${SECRING_AUTO}" \
"${SECRING_AUTO}".gpg ; \
} || { err_exit "Failed to decrypt secret key." ; }
echo "Success!"

echo -e "\nImporting keys..."
{ gpg --home "${GPG_HOME}" --import "${PUBRING_AUTO}" ; } || { err_exit "Could not import public key into gpg." ; }
{ gpg --home "${GPG_HOME}" --import "${SECRING_AUTO}" ; } || { err_exit "Could not import secret key into gpg." ; }
echo "Success!"
64 changes: 64 additions & 0 deletions .ci/gpg/pubring.auto
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----

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
dlF2O4uTr4frwKRl28eGEQ==
=ebPb
-----END PGP PUBLIC KEY BLOCK-----
Binary file added .ci/gpg/secring.auto.gpg
Binary file not shown.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
/tools/bin
/images/*/bin

# CI GPG keyring
/.ci/gpg/keyring

# Website
website/public/
website/resources/
Expand Down
90 changes: 90 additions & 0 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Global environment variables for builds.
env:
- CGO_ENABLED=0
- GO111MODULE=on
- GOPROXY=https://proxy.golang.org|direct
- REPO=github.com/operator-framework/operator-sdk

# Hooks to run before any build is run.
before:
hooks:
- go version | grep --quiet "go1\.15\.5" || echo "Go binary version must be 1.15.5"
- go mod download

# Binary builds.
builds:
# operator-sdk build steps
- id: operator-sdk
main: ./cmd/operator-sdk
binary: operator-sdk
mod_timestamp: "{{ .CommitTimestamp }}"
asmflags: &build-asmflags
- all=-trimpath={{ .Env.PWD }}
gcflags: &build-gcflags
- all=-trimpath={{ .Env.PWD }}
ldflags: &build-ldflags
- -X {{ .Env.REPO }}/internal/version.Version={{ .Env.SIMPLE_VERSION }}
- -X {{ .Env.REPO }}/internal/version.GitVersion={{ .Env.GIT_VERSION }}
- -X {{ .Env.REPO }}/internal/version.GitCommit={{ .Env.GIT_COMMIT }}
- -X {{ .Env.REPO }}/internal/version.KubernetesVersion={{ .Env.K8S_VERSION }}
- -X {{ .Env.REPO }}/internal/version.ImageVersion={{ .Env.IMAGE_VERSION }}
targets: &build-targets
- darwin_amd64
- linux_amd64
- linux_arm64
- linux_ppc64le
- linux_s390x

# ansible-operator build steps
- id: ansible-operator
main: ./cmd/ansible-operator
binary: ansible-operator
mod_timestamp: "{{ .CommitTimestamp }}"
asmflags: *build-asmflags
gcflags: *build-gcflags
ldflags: *build-ldflags
targets: *build-targets

# helm-operator build steps
- id: helm-operator
main: ./cmd/helm-operator
binary: helm-operator
mod_timestamp: "{{ .CommitTimestamp }}"
asmflags: *build-asmflags
gcflags: *build-gcflags
ldflags: *build-ldflags
targets: *build-targets

# Use most recent tag and short commit for snapshot version.
snapshot:
name_template: "{{ .Env.GIT_VERSION }}"

# We don't use archives, so skip creating them.
archives:
- format: binary
name_template: "{{ .Binary }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}{{ if .Mips }}_{{ .Mips }}{{ end }}"

checksum:
name_template: "checksums.txt"

# Sign the checksum file with the CI GPG key.
signs:
- signature: "${artifact}.asc"
artifacts: checksum
# Use the CI signing subkey A20B5C7E decrypted into .ci/gpg/keyring to sign the release.
args: ["--home", ".ci/gpg/keyring", "-u", "A20B5C7E", "--output", "${signature}", "--detach-sign", "${artifact}"]

# We use a custom changelog generator.
changelog:

# TODO(estroz): configure homebrew publishing
# brews:
# - name: operator-sdk
# ids:
# - operator-sdk

# Uncomment for testing
# release:
# github:
# owner: <your-github-namespace>
# name: operator-sdk
19 changes: 16 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ dist: xenial

language: go
go:
- 1.15.x
- 1.15.5
go_import_path: github.com/operator-framework/operator-sdk

cache:
Expand Down Expand Up @@ -47,12 +47,16 @@ x_base_steps:
- docker

stages:
- check
- test
- name: check
if: type == pull_request
- name: test
if: type == pull_request
- name: deploy
if: type != pull_request AND ( tag IS present OR branch = master OR commit_message =~ /\[travis deploy\]/ )
- name: deploy-manifest-multiarch
if: type != pull_request AND ( tag IS present OR branch = master OR commit_message =~ /\[travis deploy\]/ )
- name: release
if: type != pull_request AND tag IS present

jobs:
include:
Expand Down Expand Up @@ -151,3 +155,12 @@ jobs:
name: push manifest lists
<<: *manifest-deploy
script: make -f release/Makefile image-push-multiarch

## Release jobs ##

- stage: release
name: publish release
before_install: git fetch origin --unshallow --tags
install: sudo ln -sf $(command -v gpg2) $(dirname $(command -v gpg2))/gpg
before_script: .ci/gpg/create-keyring.sh
script: make release
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
**This file will no longer be updated. Instead, refer to generated `changelog/generated/<version>.md`**

## v1.2.0

### Additions
Expand Down
33 changes: 20 additions & 13 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ export GIT_COMMIT = $(shell git rev-parse HEAD)
export K8S_VERSION = 1.18.8

# Build settings
export TOOLS_DIR = tools/bin
export SCRIPTS_DIR = tools/scripts
REPO = $(shell go list -m)
BUILD_DIR = build
TOOLS_DIR = tools/bin
SCRIPTS_DIR = tools/scripts
GO_ASMFLAGS = -asmflags "all=-trimpath=$(shell dirname $(PWD))"
GO_GCFLAGS = -gcflags "all=-trimpath=$(shell dirname $(PWD))"
GO_BUILD_ARGS = \
Expand Down Expand Up @@ -73,7 +73,7 @@ build/scorecard-test build/scorecard-test-kuttl build/custom-scorecard-tests:
build/operator-sdk build/ansible-operator build/helm-operator:
go build $(GO_BUILD_ARGS) -o $(BUILD_DIR)/$(@F) ./cmd/$(@F)

##@ Dev images
##@ Dev image build

# Convenience wrapper for building all remotely hosted images.
.PHONY: image-build
Expand All @@ -90,6 +90,23 @@ image/%: build/%
docker build -t $(BUILD_IMAGE_REPO)/$*:dev -f ./images/$*/Dockerfile ./images/$*
rm -rf $(BUILD_DIR)

##@ Release

.PHONY: release
release: ## Release target. See 'make -f release/Makefile help' for more information.
$(MAKE) -f release/Makefile $@

.PHONY: prerelease
prerelease: ## Write release commit changes. See 'make -f release/Makefile help' for more information.
ifneq ($(RELEASE_VERSION),$(IMAGE_VERSION))
$(error "IMAGE_VERSION "$(IMAGE_VERSION)" must be updated to match RELEASE_VERSION "$(RELEASE_VERSION)" prior to creating a release commit")
endif
$(MAKE) -f release/Makefile $@

.PHONY: tag
tag: ## Tag a release commit. See 'make -f release/Makefile help' for more information.
$(MAKE) -f release/Makefile $@

##@ Test

.PHONY: test-all
Expand Down Expand Up @@ -156,16 +173,6 @@ test-e2e-integration:: ## Run integration tests
./hack/tests/integration.sh
./hack/tests/subcommand-olm-install.sh

# TODO(estroz): remove changelog/release when goreleaser is added as release tool (they shouldn't be exposed as dev targets).

.PHONY: changelog
changelog: ## Generate CHANGELOG.md and migration guide updates
$(MAKE) -f release/Makefile changelog

.PHONY: release
release: clean ## Release the Operator SDK
$(MAKE) -f release/Makefile GO_BUILD_ARGS='$(GO_BUILD_ARGS)'

.DEFAULT_GOAL := help
.PHONY: help
help: ## Show this help screen.
Expand Down
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,39 @@ operators easier by providing:
- Tools for scaffolding and code generation to bootstrap a new project fast
- Extensions to cover common operator use cases

## Dependency and platform support

### Go version

Release binaries will be built with the Go compiler version specified in the Operator SDK's [prerequisites section][doc-readme-prereqs].

### Kubernetes versions

As the Operator SDK interacts directly with the Kubernetes API, certain API features are assumed to exist in the target cluster.
The currently supported Kubernetes version will always be listed in the SDK [prerequisites section][doc-readme-prereqs].

### Platforms

The following matrix defines which architectures are supported for GNU Linux:

| | `amd64` | `arm64` | `ppc64le` | `s390x` |
|-------------------------------|-----------------|-----------------|-----------------|-----------------|
| `operator-sdk` |||||
| `ansible-operator` |||||
| `helm-operator` |||||
| `scorecard-test` image |||||
| `scorecard-test-kuttl` image |||| - |

The following matrix defines which architectures are supported for MacOS Darwin:

| | `amd64` |
|-------------------------------|-----------------|
| `operator-sdk` ||
| `ansible-operator` ||
| `helm-operator` ||

Support for the Windows platform is not on the roadmap at this time.

## License

Operator SDK is under Apache 2.0 license. See the [LICENSE][license_file] file for details.
Expand Down
28 changes: 0 additions & 28 deletions hack/image/push-image-tags.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ function push_image_tags() {
push_image=$1; shift || push_image=$source_image

print_image_info $source_image
print_git_tags

docker_login $push_image

Expand Down Expand Up @@ -53,31 +52,4 @@ function print_image_info() {
fi
}

#
# print_git_tags
#
# print_git_tags prints all tags present in the git repository.
#
function print_git_tags() {
git_tags=$(git tag -l | sed 's|^| |')
if [[ -n "$git_tags" ]]; then
echo "Found git tags:"
echo "$git_tags"
echo ""
fi
}


#
# latest_git_version
#
# latest_git_version returns the highest semantic version
# number found in the repository, with the form "vX.Y.Z".
# Version numbers not matching the semver release format
# are ignored.
#
function latest_git_version() {
git tag -l | egrep "${semver_regex}" | sort -V | tail -1
}

push_image_tags "$@"
Loading

0 comments on commit 7e490b4

Please sign in to comment.