Merge pull request #1250 from getsops/release-automation

Revamp release automation
This commit is contained in:
Hidde Beydals 2023-08-14 22:46:02 +02:00 коммит произвёл GitHub
Родитель b4b09e0906 79bbb22eff
Коммит 7fd57519ea
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
12 изменённых файлов: 699 добавлений и 184 удалений

Просмотреть файл

@ -1,3 +0,0 @@
/.git
/Dockerfile
/Dockerfile.alpine

244
.github/workflows/release.yml поставляемый
Просмотреть файл

@ -2,64 +2,200 @@ name: Release
on:
push:
tags:
- "v*"
tags: [ 'v*' ]
permissions:
contents: read
jobs:
tagged-release:
name: "Tagged Release"
release:
runs-on: ubuntu-latest
permissions:
contents: write # For creating the GitHub release.
id-token: write # For creating OIDC tokens for signing.
packages: write # For pushing and signing container images.
outputs:
artifact-subjects: "${{ steps.artifact-hashes.outputs.subjects }}"
package-subjects: "${{ steps.package-hashes.outputs.subjects }}"
sbom-subjects: "${{ steps.sbom-hashes.outputs.subjects }}"
container-subjects: "${{ steps.container-metadata.outputs.subjects }}"
steps:
- name: Install dependencies
run: sudo apt-get update && sudo apt-get install git ruby rpm -y
- name: Install fpm
run: gem install fpm || sudo gem install fpm
- name: Set up Go 1.20
uses: actions/setup-go@v3
- name: Checkout
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
with:
go-version: '1.20'
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v3
- name: Go vendor
run: go mod vendor
- name: Make release directory
run: mkdir dist
- name: Build deb and rpm
run: make deb-pkg rpm-pkg
- name: Move deb and rpm into release directory
run: mv *.deb *.rpm dist/
- name: Set RELEASE_VERSION
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
- name: Set RELEASE_NUMBER
run: echo "RELEASE_NUMBER=$(echo $RELEASE_VERSION | cut -c2-)" >> $GITHUB_ENV
- name: Build linux amd64 binary
run: GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -mod vendor -o dist/sops-${{ env.RELEASE_VERSION }}.linux.amd64 github.com/getsops/sops/v3/cmd/sops && cp dist/sops-${{ env.RELEASE_VERSION }}.linux.amd64 dist/sops-${{ env.RELEASE_VERSION }}.linux
- name: Build linux arm64 binary
run: GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -mod vendor -o dist/sops-${{ env.RELEASE_VERSION }}.linux.arm64 github.com/getsops/sops/v3/cmd/sops
- name: Build darwin amd64 binary
run: GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 go build -mod vendor -o dist/sops-${{ env.RELEASE_VERSION }}.darwin.amd64 github.com/getsops/sops/v3/cmd/sops
- name: Copy darwin amd64 to have a no-architecture labeled version
run: cp dist/sops-${{ env.RELEASE_VERSION }}.darwin.amd64 dist/sops-${{ env.RELEASE_VERSION }}.darwin
- name: Build darwin arm64 binary
run: GOOS=darwin GOARCH=arm64 CGO_ENABLED=0 go build -mod vendor -o dist/sops-${{ env.RELEASE_VERSION }}.darwin.arm64 github.com/getsops/sops/v3/cmd/sops
- name: Build windows binary
run: GOOS=windows CGO_ENABLED=0 go build -mod vendor -o dist/sops-${{ env.RELEASE_VERSION }}.exe github.com/getsops/sops/v3/cmd/sops
- name: Create release
uses: "mozilla/action-automatic-releases@latest"
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
prerelease: true
files: |
dist/sops-${{ env.RELEASE_VERSION }}.exe
dist/sops-${{ env.RELEASE_VERSION }}.darwin.amd64
dist/sops-${{ env.RELEASE_VERSION }}.darwin.arm64
dist/sops-${{ env.RELEASE_VERSION }}.darwin
dist/sops-${{ env.RELEASE_VERSION }}.linux.amd64
dist/sops-${{ env.RELEASE_VERSION }}.linux.arm64
dist/sops-${{ env.RELEASE_VERSION }}.linux
dist/sops_${{ env.RELEASE_NUMBER }}_amd64.deb
dist/sops_${{ env.RELEASE_NUMBER }}_arm64.deb
dist/sops-${{ env.RELEASE_NUMBER }}-1.x86_64.rpm
dist/sops-${{ env.RELEASE_NUMBER }}-1.aarch64.rpm
go-version: 1.20.x
cache: false
- name: Setup Syft
uses: anchore/sbom-action/download-syft@78fc58e266e87a38d4194b2137a3d4e9bcaf7ca1 # v0.14.3
- name: Setup Cosign
uses: sigstore/cosign-installer@6e04d228eb30da1757ee4e1dd75a0ec73a653e06 # v3.1.1
- name: Setup QEMU
uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7 # v2.2.0
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@4c0219f9ac95b02789c1075625400b2acbff50b1 # v2.9.1
- name: Login to GitHub Container Registry
uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc # v2.2.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to Quay.io
uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc # v2.2.0
with:
registry: quay.io
username: ${{ secrets.QUAY_BOT_USERNAME }}
password: ${{ secrets.QUAY_BOT_TOKEN }}
- name: Run GoReleaser
id: goreleaser
uses: goreleaser/goreleaser-action@336e29918d653399e599bfca99fadc1d7ffbc9f7 # v4.3.0
with:
version: 1.20.x
args: release --clean --timeout 1h
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Extract artifact subjects
id: artifact-hashes
env:
ARTIFACTS: "${{ steps.goreleaser.outputs.artifacts }}"
run: |
set -euo pipefail
sum_file=$(echo -E $ARTIFACTS | jq -r '.[] | {name, "digest": (.extra.Digest // .extra.Checksum)} | select(.digest) | {digest} + {name} | join(" ") | sub("^(.*?):";"")')
echo "subjects=$(echo "$sum_file" | base64 -w0)" >> "$GITHUB_OUTPUT"
- name: Extract package subjects
id: package-hashes
env:
ARTIFACTS: "${{ steps.goreleaser.outputs.artifacts }}"
run: |
set -euo pipefail
sum_file="$(mktemp)"
mapfile -t file_paths < <(echo -E "$ARTIFACTS" | jq -r '.[] | select(.type=="Linux Package") | .path')
for f in "${file_paths[@]}"; do
file_name=$(basename "$f")
file_sum=$(sha256sum "$f" | awk '{print $1}')
echo "$file_sum $file_name" >> "$sum_file"
done
echo "subjects=$(base64 -w0 < "$sum_file")" >> "$GITHUB_OUTPUT"
- name: Extract SBOM subjects
id: sbom-hashes
env:
ARTIFACTS: "${{ steps.goreleaser.outputs.artifacts }}"
run: |
set -euo pipefail
sum_file="$(mktemp)"
mapfile -t file_paths < <(echo -E "$ARTIFACTS" | jq -r '.[] | select(.type=="SBOM") | .path')
for f in "${file_paths[@]}"; do
file_name=$(basename "$f")
file_sum=$(sha256sum "$f" | awk '{print $1}')
echo "$file_sum $file_name" >> "$sum_file"
done
echo "subjects=$(base64 -w0 < "$sum_file")" >> "$GITHUB_OUTPUT"
- name: Extract container image subjects
id: container-metadata
env:
ARTIFACTS: "${{ steps.goreleaser.outputs.artifacts }}"
run: |
image_list=$(echo -e "$ARTIFACTS" | jq -r '.[] | select(.type=="Docker Manifest") | {"image": (.name | sub("^.*?/"; "") | sub(":(.*)"; "")), "digest": .extra.Digest}')
echo "subjects=$(echo $image_list | jq -c -s 'unique_by(.digest) | {"include": .}')" >> "$GITHUB_OUTPUT"
combine-subjects:
runs-on: ubuntu-latest
needs: [ release ]
outputs:
all-subjects: "${{ steps.combine-subjects.outputs.subjects }}"
steps:
- name: Combine subjects
id: combine-subjects
env:
ARTIFACT_SUBJECTS: "${{ needs.release.outputs.artifact-subjects }}"
PACKAGE_SUBJECTS: "${{ needs.release.outputs.package-subjects }}"
SBOM_SUBJECTS: "${{ needs.release.outputs.sbom-subjects }}"
run: |
set -euo pipefail
artifact_subjects=$(echo "$ARTIFACT_SUBJECTS" | base64 -d)
package_subjects=$(echo "$PACKAGE_SUBJECTS" | base64 -d)
sbom_subjects=$(echo "$SBOM_SUBJECTS" | base64 -d)
all_subjects=$(echo -e "${artifact_subjects}\n${package_subjects}\n${sbom_subjects}\n" | sed '/^$/d')
echo "subjects=$(echo "$all_subjects" | base64 -w0)" >> "$GITHUB_OUTPUT"
assets-provenance:
needs: [ combine-subjects ]
permissions:
actions: read # For detecting the GitHub Actions environment.
id-token: write # For creating OIDC tokens for signing.
contents: write # For adding assets to a release.
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.8.0
with:
base64-subjects: "${{ needs.combine-subjects.outputs.all-subjects }}"
upload-assets: true
provenance-name: "provenance.intoto.jsonl"
ghcr-container-provenance:
needs: [ release ]
permissions:
actions: read # For detecting the Github Actions environment.
id-token: write # For creating OIDC tokens for signing.
packages: write # For uploading attestations.
strategy:
matrix: ${{ fromJSON(needs.release.outputs.container-subjects) }}
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v1.8.0
with:
image: ghcr.io/${{ matrix.image }}
digest: ${{ matrix.digest }}
registry-username: ${{ github.actor }}
secrets:
registry-password: ${{ secrets.GITHUB_TOKEN }}
quay-container-provenance:
needs: [ release ]
permissions:
actions: read # For detecting the Github Actions environment.
id-token: write # For creating OIDC tokens for signing.
packages: write # For uploading attestations.
strategy:
matrix: ${{ fromJSON(needs.release.outputs.container-subjects) }}
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v1.8.0
with:
image: quay.io/${{ matrix.image }}
digest: ${{ matrix.digest }}
secrets:
registry-username: ${{ secrets.QUAY_BOT_USERNAME }}
registry-password: ${{ secrets.QUAY_BOT_TOKEN }}

3
.gitignore поставляемый
Просмотреть файл

@ -1,4 +1,5 @@
target
bin/
dist/
Cargo.lock
vendor/
coverage.txt

370
.goreleaser.yaml Normal file
Просмотреть файл

@ -0,0 +1,370 @@
# yaml-language-server: $schema=https://goreleaser.com/static/schema.json
project_name: sops
# xref: https://goreleaser.com/customization/hooks/
before:
hooks:
- go mod download
# xref: https://goreleaser.com/customization/env/
env:
- CGO_ENABLED=0
- PKG=github.com/getsops/sops/v3/version
- COSIGN_YES=true
# xref: https://goreleaser.com/customization/reportsizes/
report_sizes: true
# xref: https://goreleaser.com/customization/build/
builds:
- id: binary-linux
main: ./cmd/sops
binary: "{{ .ProjectName }}"
flags:
- -trimpath
- -mod=readonly
ldflags:
- >
-s -w
-X {{ .Env.PKG }}.Version={{ .Version }}"
goos:
- linux
goarch:
- amd64
- arm64
# Modified timestamp on the binary, set to ensure reproducible builds.
mod_timestamp: "{{ .CommitTimestamp }}"
- id: binary-darwin
main: ./cmd/sops
binary: "{{ .ProjectName }}"
flags:
- -trimpath
- -mod=readonly
ldflags:
- >
-s -w
-X {{ .Env.PKG }}.Version={{ .Version }}
goos:
- darwin
goarch:
- amd64
- arm64
# Modified timestamp on the binary, set to ensure reproducible builds.
mod_timestamp: "{{ .CommitTimestamp }}"
- id: binary-windows
main: ./cmd/sops
binary: "{{ .ProjectName }}"
flags:
- -trimpath
- -buildmode=pie
- -mod=readonly
ldflags:
- >
-s -w
-X {{ .Env.PKG }}.Version={{ .Version }}
goos:
- windows
goarch:
- amd64
# Modified timestamp on the binary, set to ensure reproducible builds.
mod_timestamp: "{{ .CommitTimestamp }}"
# xref: https://goreleaser.com/customization/universalbinaries/
universal_binaries:
- id: binary-darwin-universal
ids:
- binary-darwin
name_template: '{{ .ProjectName }}'
# We want to continue to ship individual binaries for darwin/amd64 and
# darwin/arm64.
replace: false
# Modified timestamp on the binary, set to ensure reproducible builds.
# NB: Available in GoReleaser >=1.20.0.
mod_timestamp: "{{ .CommitTimestamp }}"
# xref: https://goreleaser.com/customization/nfpm/
nfpms:
- id: deb
package_name: '{{ .ProjectName }}'
file_name_template: '{{ .ConventionalFileName }}'
vendor: CNCF SOPS
homepage: https://github.com/{{ .Env.GITHUB_REPOSITORY }}
maintainer: SOPS maintainers <cncf-SOPS-maintainers@lists.cncf.io>
description: Simple and flexible tool for managing secrets
license: MPL-2.0
formats:
- deb
- rpm
# xref: https://goreleaser.com/customization/snapshots/
snapshot:
name_template: "{{ incpatch .Version }}-dev-{{ .ShortCommit }}"
# xref: https://goreleaser.com/customization/archive/#disable-archiving
archives:
- id: archive-unix
format: binary
builds:
- binary-linux
- binary-darwin
# NB: specifically crafted to ensure compatibility with release artifacts < v3.8.0.
name_template: '{{ .ProjectName }}-v{{ .Version }}.{{ .Os }}.{{ .Arch }}'
- id: archive-windows
format: binary
builds:
- binary-windows
# NB: specifically crafted to ensure compatibility with release artifacts < v3.8.0.
name_template: '{{ .ProjectName }}-v{{ .Version }}'
- id: archive-darwin-universal
format: binary
builds:
- binary-darwin-universal
# NB: specifically crafted to ensure compatibility with release artifacts < v3.8.0.
# We can't bundle this with the other unix archive, because .Arch becomes "all".
# Before v3.8.0, this used to be _just_ the AMD64 binary.
name_template: '{{ .ProjectName }}-v{{ .Version }}.darwin'
# xref: https://goreleaser.com/customization/checksum/
checksum:
name_template: "{{ .ProjectName }}-v{{ .Version }}.checksums.txt"
algorithm: sha256
ids:
- archive-unix
- archive-windows
- archive-darwin-universal
# xref: https://goreleaser.com/customization/sbom/
sboms:
- id: binary-sbom
artifacts: binary
documents:
- "{{ .ArtifactName }}.spdx.sbom.json"
# xref: https://goreleaser.com/customization/sign/
signs:
- cmd: cosign
artifacts: checksum
signature: '{{ trimsuffix .Env.artifact ".txt" }}.sig'
certificate: '{{ trimsuffix .Env.artifact ".txt" }}.pem'
args:
- "sign-blob"
- "--output-signature"
- "${signature}"
- "--output-certificate"
- "${certificate}"
- "${artifact}"
output: true
# xref: https://goreleaser.com/customization/docker/
dockers:
- image_templates:
- 'ghcr.io/{{ .Env.GITHUB_REPOSITORY }}:v{{ .Version }}-amd64'
- 'quay.io/{{ .Env.GITHUB_REPOSITORY }}:v{{ .Version }}-amd64'
use: buildx
goos: linux
goarch: amd64
ids:
- binary-linux
dockerfile: .release/Dockerfile
build_flag_templates:
- "--pull"
- "--platform=linux/amd64"
- "--label=org.opencontainers.image.created={{ .Date }}"
- "--label=org.opencontainers.image.title={{ .ProjectName }}"
- "--label=org.opencontainers.image.revision={{ .FullCommit }}"
- "--label=org.opencontainers.image.version={{ .Version }}"
- "--label=org.opencontainers.image.source={{ .GitURL }}"
- image_templates:
- 'ghcr.io/{{ .Env.GITHUB_REPOSITORY }}:v{{ .Version }}-arm64'
- 'quay.io/{{ .Env.GITHUB_REPOSITORY }}:v{{ .Version }}-arm64'
use: buildx
goos: linux
goarch: arm64
ids:
- binary-linux
dockerfile: .release/Dockerfile
build_flag_templates:
- "--pull"
- "--platform=linux/arm64"
- "--label=org.opencontainers.image.created={{ .Date }}"
- "--label=org.opencontainers.image.title={{ .ProjectName }}"
- "--label=org.opencontainers.image.revision={{ .FullCommit }}"
- "--label=org.opencontainers.image.version={{ .Version }}"
- "--label=org.opencontainers.image.source={{ .GitURL }}"
- image_templates:
- 'ghcr.io/{{ .Env.GITHUB_REPOSITORY }}:v{{ .Version }}-alpine-amd64'
- 'quay.io/{{ .Env.GITHUB_REPOSITORY }}:v{{ .Version }}-alpine-amd64'
use: buildx
goos: linux
goarch: amd64
ids:
- binary-linux
dockerfile: .release/alpine.Dockerfile
build_flag_templates:
- "--pull"
- "--platform=linux/amd64"
- "--label=org.opencontainers.image.created={{ .Date }}"
- "--label=org.opencontainers.image.title={{ .ProjectName }}"
- "--label=org.opencontainers.image.revision={{ .FullCommit }}"
- "--label=org.opencontainers.image.version={{ .Version }}"
- "--label=org.opencontainers.image.source={{ .GitURL }}"
- image_templates:
- 'ghcr.io/{{ .Env.GITHUB_REPOSITORY }}:v{{ .Version }}-alpine-arm64'
- 'quay.io/{{ .Env.GITHUB_REPOSITORY }}:v{{ .Version }}-alpine-arm64'
use: buildx
goos: linux
goarch: arm64
ids:
- binary-linux
dockerfile: .release/alpine.Dockerfile
build_flag_templates:
- "--pull"
- "--platform=linux/arm64"
- "--label=org.opencontainers.image.created={{ .Date }}"
- "--label=org.opencontainers.image.title={{ .ProjectName }}"
- "--label=org.opencontainers.image.revision={{ .FullCommit }}"
- "--label=org.opencontainers.image.version={{ .Version }}"
- "--label=org.opencontainers.image.source={{ .GitURL }}"
# xref: https://goreleaser.com/customization/docker_manifest/
docker_manifests:
- name_template: 'ghcr.io/{{ .Env.GITHUB_REPOSITORY }}:v{{ .Version }}'
image_templates:
- 'ghcr.io/{{ .Env.GITHUB_REPOSITORY }}:v{{ .Version }}-amd64'
- 'ghcr.io/{{ .Env.GITHUB_REPOSITORY }}:v{{ .Version }}-arm64'
- name_template: 'ghcr.io/{{ .Env.GITHUB_REPOSITORY }}:v{{ .Version }}-alpine'
image_templates:
- 'ghcr.io/{{ .Env.GITHUB_REPOSITORY }}:v{{ .Version }}-alpine-amd64'
- 'ghcr.io/{{ .Env.GITHUB_REPOSITORY }}:v{{ .Version }}-alpine-arm64'
- name_template: 'quay.io/{{ .Env.GITHUB_REPOSITORY }}:v{{ .Version }}'
image_templates:
- 'quay.io/{{ .Env.GITHUB_REPOSITORY }}:v{{ .Version }}-amd64'
- 'quay.io/{{ .Env.GITHUB_REPOSITORY }}:v{{ .Version }}-arm64'
- name_template: 'quay.io/{{ .Env.GITHUB_REPOSITORY }}:v{{ .Version }}-alpine'
image_templates:
- 'quay.io/{{ .Env.GITHUB_REPOSITORY }}:v{{ .Version }}-alpine-amd64'
- 'quay.io/{{ .Env.GITHUB_REPOSITORY }}:v{{ .Version }}-alpine-arm64'
# xref: https://goreleaser.com/customization/docker_sign/
docker_signs:
- cmd: cosign
artifacts: all
output: true
args:
- "sign"
- "${artifact}@${digest}"
# xref: https://goreleaser.com/customization/changelog/
changelog:
# xref: https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes#configuration-options
# xref: https://docs.github.com/en/free-pro-team@latest/rest/releases/releases?apiVersion=2022-11-28#generate-release-notes-content-for-a-release
use: github-native
# xref: https://goreleaser.com/customization/release/
release:
prerelease: auto
header: |
## Installation
To install `{{ .ProjectName }}`, download one of the pre-built binaries provided for your platform from the artifacts attached to this release.
For instance, if you are using Linux on an AMD64 architecture:
```shell
# Download the binary
curl -LO https://github.com/{{ .Env.GITHUB_REPOSITORY }}/releases/download/{{ .Tag }}/{{ .ProjectName }}-v{{ .Version }}.linux.amd64
# Move the binary in to your PATH
mv {{ .ProjectName }}-v{{ .Version }}.linux.amd64 /usr/local/bin/{{ .ProjectName }}
# Make the binary executable
chmod +x /usr/local/bin/{{ .ProjectName }}
```
### Verify checksums file signature
The checksums file provided within the artifacts attached to this release is signed using [Cosign](https://docs.sigstore.dev/cosign/overview/) with GitHub OIDC. To validate the signature of this file, run the following commands:
```shell
# Download the checksums file, certificate and signature
curl -LO https://github.com/{{ .Env.GITHUB_REPOSITORY }}/releases/download/{{ .Tag }}/{{ .ProjectName }}-v{{ .Version }}.checksums.txt
curl -LO https://github.com/{{ .Env.GITHUB_REPOSITORY }}/releases/download/{{ .Tag }}/{{ .ProjectName }}-v{{ .Version }}.checksums.pem
curl -LO https://github.com/{{ .Env.GITHUB_REPOSITORY }}/releases/download/{{ .Tag }}/{{ .ProjectName }}-v{{ .Version }}.checksums.sig
# Verify the checksums file
cosign verify-blob {{ .ProjectName }}-v{{ .Version }}.checksums.txt \
--certificate {{ .ProjectName }}-v{{ .Version }}.checksums.pem \
--signature {{ .ProjectName }}-v{{ .Version }}.checksums.sig \
--certificate-identity-regexp=https://github.com/{{ .Env.GITHUB_REPOSITORY_OWNER }} \
--certificate-oidc-issuer=https://token.actions.githubusercontent.com
```
### Verify binary integrity
To verify the integrity of the downloaded binary, you can utilize the checksums file after having validated its signature:
```shell
# Verify the binary using the checksums file
sha256sum -c {{ .ProjectName }}-v{{ .Version }}.checksums.txt --ignore-missing
```
### Verify artifact provenance
The [SLSA provenance](https://slsa.dev/provenance/v0.2) of the binaries, packages, and SBOMs can be found within the artifacts associated with this release. It is presented through an [in-toto](https://in-toto.io/) link metadata file named `provenance.intoto.jsonl`. To verify the provenance of an artifact, you can utilize the [`slsa-verifier`](https://github.com/slsa-framework/slsa-verifier#artifacts) tool:
```shell
# Download the metadata file
curl -LO https://github.com/{{ .Env.GITHUB_REPOSITORY }}/releases/download/{{ .Tag }}/provenance.intoto.jsonl
# Verify the provenance of the artifact
slsa-verifier verify-artifact <artifact> \
--provenance-path provenance.intoto.jsonl \
--source-uri github.com/{{ .Env.GITHUB_REPOSITORY }} \
--source-tag {{ .Tag }}
```
## Container Images
The `{{ .ProjectName }}` binaries are also available as container images, based on Debian (slim) and Alpine Linux. The Debian-based container images include any dependencies which may be required to make use of certain key services, such as GnuPG, AWS KMS, Azure Key Vault, and Google Cloud KMS. The Alpine-based container images are smaller in size, but do not include these dependencies.
These container images are available for the following architectures: `linux/amd64` and `linux/arm64`.
### GitHub Container Registry
- `ghcr.io/{{ .Env.GITHUB_REPOSITORY }}:v{{ .Version }}`
- `ghcr.io/{{ .Env.GITHUB_REPOSITORY }}:v{{ .Version }}-alpine`
### Quay.io
- `quay.io/{{ .Env.GITHUB_REPOSITORY }}:v{{ .Version }}`
- `quay.io/{{ .Env.GITHUB_REPOSITORY }}:v{{ .Version }}-alpine`
### Verify container image signature
The container images are signed using [Cosign](https://docs.sigstore.dev/cosign/overview/) with GitHub OIDC. To validate the signature of an image, run the following command:
```shell
cosign verify ghcr.io/{{ .Env.GITHUB_REPOSITORY }}:v{{ .Version }} \
--certificate-identity-regexp=https://github.com/{{ .Env.GITHUB_REPOSITORY_OWNER }} \
--certificate-oidc-issuer=https://token.actions.githubusercontent.com \
-o text
```
### Verify container image provenance
The container images include [SLSA provenance](https://slsa.dev/provenance/v0.2) attestations. For more information around the verification of this, please refer to the [`slsa-verifier` documentation](https://github.com/slsa-framework/slsa-verifier#containers).
## Software Bill of Materials
The Software Bill of Materials (SBOM) for each binary is accessible within the artifacts enclosed with this release. It is presented as an [SPDX](https://spdx.dev/) JSON file, formatted as `<binary>.spdx.sbom.json`.

16
.release/Dockerfile Normal file
Просмотреть файл

@ -0,0 +1,16 @@
FROM debian:bookworm-slim
RUN apt-get update && apt-get install --no-install-recommends -y \
awscli \
azure-cli \
curl \
gnupg \
vim \
&& rm -rf /var/lib/apt/lists/*
ENV EDITOR vim
# Glob pattern to match the binary for the current architecture
COPY sops* /usr/local/bin/sops
ENTRYPOINT ["sops"]

Просмотреть файл

@ -0,0 +1,13 @@
FROM alpine:3.18
RUN apk --no-cache add \
ca-certificates \
vim \
&& update-ca-certificates
ENV EDITOR vim
# Glob pattern to match the binary for the current architecture
COPY sops* /usr/local/bin/sops
ENTRYPOINT ["sops"]

Просмотреть файл

@ -1,10 +0,0 @@
FROM golang:1.20
COPY . /go/src/github.com/getsops/sops/v3
WORKDIR /go/src/github.com/getsops/sops/v3
RUN CGO_ENABLED=1 make install
RUN apt-get update
RUN apt-get install -y vim python3-pip emacs
RUN pip install awscli
ENV EDITOR vim

Просмотреть файл

@ -1,17 +0,0 @@
FROM golang:1.20-alpine3.18 AS builder
RUN apk --no-cache add make
COPY . /go/src/github.com/getsops/sops/v3
WORKDIR /go/src/github.com/getsops/sops/v3
RUN CGO_ENABLED=1 make install
FROM alpine:3.18
RUN apk --no-cache add \
vim ca-certificates
ENV EDITOR vim
COPY --from=builder /go/bin/sops /usr/local/bin/sops
ENTRYPOINT ["/usr/local/bin/sops"]

Просмотреть файл

@ -2,11 +2,20 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
PROJECT := github.com/getsops/sops/v3
GO := GOPROXY=https://proxy.golang.org go
GOLINT := golint
PROJECT := github.com/getsops/sops/v3
PROJECT_DIR := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST))))
GO := GOPROXY=https://proxy.golang.org go
GOLINT := golint
GITHUB_REPOSITORY ?= github.com/getsops/sops
GORELEASER := $(PROJECT_DIR)/bin/goreleaser
GORELEASER_VERSION ?= v1.20.0
.PHONY: all
all: test vet generate install functional-tests
.PHONY: origin-build
origin-build: test vet generate install functional-tests-all
install:
@ -18,6 +27,7 @@ tag: all
lint:
$(GOLINT) $(PROJECT)
.PHONY: vendor
vendor:
$(GO) mod tidy
$(GO) mod vendor
@ -25,6 +35,7 @@ vendor:
vet:
$(GO) vet $(PROJECT)
.PHONY: test
test: vendor
gpg --import pgp/sops_functional_tests_key.asc 2>&1 1>/dev/null || exit 0
./test.sh
@ -32,81 +43,38 @@ test: vendor
showcoverage: test
$(GO) tool cover -html=coverage.out
.PHONY: generate
generate: keyservice/keyservice.pb.go
$(GO) generate
%.pb.go: %.proto
protoc --go_out=plugins=grpc:. $<
.PHONY: functional-tests
functional-tests:
$(GO) build -o functional-tests/sops github.com/getsops/sops/v3/cmd/sops
cd functional-tests && cargo test
# Ignored tests are ones that require external services (e.g. AWS KMS)
# TODO: Once `--include-ignored` lands in rust stable, switch to that.
.PHONY: functional-tests-all
functional-tests-all:
$(GO) build -o functional-tests/sops github.com/getsops/sops/v3/cmd/sops
# Ignored tests are ones that require external services (e.g. AWS KMS)
# TODO: Once `--include-ignored` lands in rust stable, switch to that.
cd functional-tests && cargo test && cargo test -- --ignored
# Creates variables during target re-definition. Basically this block allows the particular variables to be used in the final target
build-deb-%: OS = $(word 1,$(subst -, ,$*))
build-deb-%: ARCH = $(word 2,$(subst -, ,$*))
build-deb-%: FPM_ARCH = $(word 3,$(subst -, ,$*))
# Poor-mans function with parameters being split out from the variable part of it's name
build-deb-%:
rm -rf tmppkg
mkdir -p tmppkg/usr/local/bin
GOOS=$(OS) GOARCH="$(ARCH)" CGO_ENABLED=0 go build -mod vendor -o tmppkg/usr/local/bin/sops github.com/getsops/sops/v3/cmd/sops
fpm -C tmppkg -n sops --license MPL2.0 --vendor mozilla \
--description "Sops is an editor of encrypted files that supports YAML, JSON and BINARY formats and encrypts with AWS KMS and PGP." \
-m "AJ Bahnken <ajvb+sops@mozilla.com>" \
--url https://github.com/getsops/sops/v3 \
--architecture $(FPM_ARCH) \
-v "$$(grep '^const Version' version/version.go |cut -d \" -f 2)" \
-s dir -t deb .
.PHONY: release-snapshot
release-snapshot: install-goreleaser
GITHUB_REPOSITORY=$(GITHUB_REPOSITORY) $(GORELEASER) release --clean --snapshot --skip-sign
# Create .deb packages for multiple architectures
deb-pkg: vendor build-deb-linux-amd64-x86_64 build-deb-linux-arm64-arm64
.PHONY: install-goreleaser
install-goreleaser:
$(call go-install-tool,$(GORELEASER),github.com/goreleaser/goreleaser@$(GORELEASER_VERSION),$(GORELEASER_VERSION))
# Creates variables during target re-definition. Basically this block allows the particular variables to be used in the final target
build-rpm-%: OS = $(word 1,$(subst -, ,$*))
build-rpm-%: ARCH = $(word 2,$(subst -, ,$*))
build-rpm-%: FPM_ARCH = $(word 3,$(subst -, ,$*))
# Poor-mans function with parameters being split out from the variable part of it's name
build-rpm-%:
rm -rf tmppkg
mkdir -p tmppkg/usr/local/bin
GOOS=$(OS) GOARCH="$(ARCH)" CGO_ENABLED=0 go build -mod vendor -o tmppkg/usr/local/bin/sops github.com/getsops/sops/v3/cmd/sops
fpm -C tmppkg -n sops --license MPL2.0 --vendor mozilla \
--description "Sops is an editor of encrypted files that supports YAML, JSON and BINARY formats and encrypts with AWS KMS and PGP." \
-m "AJ Bahnken <ajvb+sops@mozilla.com>" \
--url https://github.com/getsops/sops/v3 \
--architecture $(FPM_ARCH) \
--rpm-os $(OS) \
-v "$$(grep '^const Version' version/version.go |cut -d \" -f 2)" \
-s dir -t rpm .
# Create .rpm packages for multiple architectures
rpm-pkg: vendor build-rpm-linux-amd64-x86_64 build-rpm-linux-arm64-arm64
dmg-pkg: install
ifneq ($(OS),darwin)
echo 'you must be on MacOS and set OS=darwin on the make command line to build an OSX package'
else
rm -rf tmppkg
mkdir -p tmppkg/usr/local/bin
cp $$GOPATH/bin/sops tmppkg/usr/local/bin/
fpm -C tmppkg -n sops --license MPL2.0 --vendor mozilla \
--description "Sops is an editor of encrypted files that supports YAML, JSON and BINARY formats and encrypts with AWS KMS and PGP." \
-m "Mozilla Security <security@mozilla.org>" \
--url https://github.com/getsops/sops/v3 \
--architecture x86_64 \
-v "$$(grep '^const Version' version/version.go |cut -d \" -f 2)" \
-s dir -t osxpkg \
--osxpkg-identifier-prefix org.mozilla.sops \
-p tmppkg/sops-$$(git describe --abbrev=0 --tags).pkg .
hdiutil makehybrid -hfs -hfs-volume-name "Mozilla Sops" \
-o tmppkg/sops-$$(git describe --abbrev=0 --tags).dmg tmpdmg
endif
.PHONY: all test generate clean vendor functional-tests
# go-install-tool will 'go install' any package $2 and install it to $1.
define go-install-tool
@[ -f $(1)-$(3) ] || { \
set -e ;\
GOBIN=$$(dirname $(1)) go install $(2) ;\
touch $(1)-$(3) ;\
}
endef

Просмотреть файл

@ -1,33 +0,0 @@
#!/bin/bash
# THIS IS MEANT TO BE RUN BY CI
set -e
set +x
# Usage: retry MAX CMD...
# Retry CMD up to MAX times. If it fails MAX times, returns failure.
# Example: retry 3 docker push "mozilla/sops:$TAG"
function retry() {
max=$1
shift
count=1
until "$@"; do
count=$((count + 1))
if [[ $count -gt $max ]]; then
return 1
fi
echo "$count / $max"
done
return 0
}
if [[ "$DOCKER_DEPLOY" == "true" ]]; then
# configure docker creds
retry 3 docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD"
# docker tag and push git branch to dockerhub
if [ -n "$1" ]; then
retry 3 docker push "mozilla/sops:$1" ||
(echo "Couldn't push mozilla/sops:$1" && false)
echo "Pushed mozilla/sops:$1"
fi
fi

74
docs/release.md Normal file
Просмотреть файл

@ -0,0 +1,74 @@
# Release procedure
This document describes the procedure for releasing a new version of SOPS. It
is intended for maintainers of the project, but may be useful for anyone
interested in the release process.
## Overview
The release is performed by creating a signed tag for the release, and pushing
it to GitHub. This will automatically trigger a GitHub Actions workflow that
builds the binaries, packages, SBOMs, and other artifacts for the release
using [GoReleaser](https://goreleaser.com), and uploads them to GitHub.
The configuration for GoReleaser is in the file
[`.goreleaser.yaml`](../.goreleaser.yaml). The configuration for the GitHub
Actions workflow is in the file
[`release.yml`](../.github/workflows/release.yml).
This configuration is quite sophisticated, and ensures at least the following:
- The release is built for multiple platforms and architectures, including
Linux, macOS, and Windows, and for both AMD64 and ARM64.
- The release includes multiple packages in Debian and RPM formats.
- For every binary, a corresponding SBOM is generated and published.
- For all binaries, a checksum file is generated and signed using
[Cosign](https://docs.sigstore.dev/cosign/overview/) with GitHub OIDC.
- Both Debian and Alpine Docker multi-arch images are built and pushed to GitHub
Container Registry and Quay.io.
- The container images are signed using
[Cosign](https://docs.sigstore.dev/cosign/overview/) with GitHub OIDC.
- [SLSA provenance](https://slsa.dev/provenance/v0.2) metadata is generated for
release artifacts and container images.
## Preparation
- [ ] Ensure that all changes intended for the release are merged into the
`main` branch. At present, this means that all pull requests attached to the
milestone for the release are merged. If there are any pull requests that
should not be included in the release, move them to a different milestone.
- [ ] Create a pull request to update the [`CHANGELOG.rst`](../CHANGELOG.rst)
file. This should include a summary of all changes since the last release,
including references to any relevant pull requests.
- [ ] In this same pull request, update the version number in `version/version.go`
to the new version number.
- [ ] Get approval for the pull request from at least one other maintainer, and
merge it into `main`.
- [ ] Ensure CI passes on the `main` branch.
## Release
- [ ] Ensure your local copy of the `main` branch is up-to-date:
```sh
git checkout main
git pull
```
- [ ] Create a **signed tag** for the release, using the following command:
```sh
git tag -s -m <version> <version>
```
where `<version>` is the version number of the release. The version number
should be in the form `vX.Y.Z`, where `X`, `Y`, and `Z` are integers. The
version number should be incremented according to
[semantic versioning](https://semver.org/).
- [ ] Push the tag to GitHub:
```sh
git push origin <version>
```
- [ ] Ensure the release is built successfully on GitHub Actions. This will
automatically create a release on GitHub.

Просмотреть файл

@ -11,7 +11,7 @@ import (
)
// Version represents the value of the current semantic version
const Version = "3.7.3"
var Version = "3.7.3"
// PrintVersion handles the version command for sops
func PrintVersion(c *cli.Context) {