Skip to content

Commit 2332832

Browse files
committed
Add basic CI/CD for building and releasing
1 parent fdb5eeb commit 2332832

File tree

10 files changed

+315
-2
lines changed

10 files changed

+315
-2
lines changed

.github/workflows/docker-publish.yml

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
name: Docker
2+
3+
on:
4+
push:
5+
branches: [ "main" ]
6+
# Publish semver tags as releases.
7+
tags: [ 'v*.*.*' ]
8+
pull_request:
9+
branches: [ "main" ]
10+
11+
env:
12+
# Use docker.io for Docker Hub if empty
13+
REGISTRY: ghcr.io
14+
# github.repository as <account>/<repo>
15+
IMAGE_NAME: ${{ github.repository }}
16+
17+
18+
jobs:
19+
build:
20+
21+
runs-on: ubuntu-latest
22+
permissions:
23+
contents: read
24+
packages: write
25+
# This is used to complete the identity challenge
26+
# with sigstore/fulcio when running outside of PRs.
27+
id-token: write
28+
29+
steps:
30+
- name: Checkout repository
31+
uses: actions/checkout@v4
32+
33+
# Install the cosign tool except on PR
34+
# https://github.com/sigstore/cosign-installer
35+
- name: Install cosign
36+
if: github.event_name != 'pull_request'
37+
uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 #v3.5.0
38+
with:
39+
cosign-release: 'v2.2.4'
40+
41+
# Set up BuildKit Docker container builder to be able to build
42+
# multi-platform images and export cache
43+
# https://github.com/docker/setup-buildx-action
44+
- name: Set up Docker Buildx
45+
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
46+
47+
# Login against a Docker registry except on PR
48+
# https://github.com/docker/login-action
49+
- name: Log into registry ${{ env.REGISTRY }}
50+
if: github.event_name != 'pull_request'
51+
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
52+
with:
53+
registry: ${{ env.REGISTRY }}
54+
username: ${{ github.actor }}
55+
password: ${{ secrets.GITHUB_TOKEN }}
56+
57+
# Extract metadata (tags, labels) for Docker
58+
# https://github.com/docker/metadata-action
59+
- name: Extract Docker metadata
60+
id: meta
61+
uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0
62+
with:
63+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
64+
65+
- name: Set VERSION in env
66+
run: echo "VERSION=${GITHUB_REF_NAME/\//-}" >> $GITHUB_ENV
67+
68+
# Build and push Docker image with Buildx (don't push on PR)
69+
# https://github.com/docker/build-push-action
70+
- name: Build and push Docker image
71+
id: build-and-push
72+
uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0
73+
with:
74+
context: .
75+
push: ${{ github.event_name != 'pull_request' }}
76+
platforms: linux/amd64,linux/arm64
77+
tags: ${{ steps.meta.outputs.tags }}
78+
labels: ${{ steps.meta.outputs.labels }}
79+
cache-from: type=gha
80+
cache-to: type=gha,mode=max
81+
build-args: VERSION=${{ env.VERSION }}
82+
83+
# Sign the resulting Docker image digest except on PRs.
84+
# This will only write to the public Rekor transparency log when the Docker
85+
# repository is public to avoid leaking data. If you would like to publish
86+
# transparency data even for private images, pass --force to cosign below.
87+
# https://github.com/sigstore/cosign
88+
- name: Sign the published Docker image
89+
if: ${{ github.event_name != 'pull_request' }}
90+
env:
91+
# https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable
92+
TAGS: ${{ steps.meta.outputs.tags }}
93+
DIGEST: ${{ steps.build-and-push.outputs.digest }}
94+
# This step uses the identity token to provision an ephemeral certificate
95+
# against the sigstore community Fulcio instance.
96+
run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST}

.github/workflows/release.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: Create Release
2+
3+
on:
4+
push:
5+
branches: [ "cicd" ]
6+
# Publish semver tags as releases.
7+
tags: [ 'v*.*.*' ]
8+
9+
env:
10+
REGISTRY: ghcr.io
11+
IMAGE_NAME: ${{ github.repository }}
12+
13+
jobs:
14+
release:
15+
permissions:
16+
contents: write # for softprops/action-gh-release to create/update GitHub release
17+
name: update release
18+
runs-on: ubuntu-latest
19+
steps:
20+
- name: Set env
21+
run: echo "RELEASE_TAG=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
22+
- name: checkout code
23+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # tag=v4.2.2
24+
with:
25+
fetch-depth: 0
26+
ref: ${{ env.RELEASE_TAG }}
27+
- name: Set up Go
28+
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # tag=v5.5.0
29+
with:
30+
go-version-file: go.mod
31+
- name: generate release artifacts
32+
env:
33+
IMG: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.RELEASE_TAG }}
34+
run: make release
35+
- name: Release
36+
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631 # tag=v2.2.2
37+
with:
38+
prerelease: false
39+
generate_release_notes: true
40+
files: out/*
41+
tag_name: ${{ env.RELEASE_TAG }}

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,6 @@ go.work
2525
*.swp
2626
*.swo
2727
*~
28+
29+
# release directory
30+
out/*

Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
FROM golang:1.24 AS builder
33
ARG TARGETOS
44
ARG TARGETARCH
5+
ARG VERSION
56

67
WORKDIR /workspace
78
# Copy the Go Modules manifests
@@ -21,7 +22,7 @@ COPY internal/ internal/
2122
# was called. For example, if we call make docker-build in a local env which has the Apple Silicon M1 SO
2223
# the docker BUILDPLATFORM arg will be linux/arm64 when for Apple x86 it will be linux/amd64. Therefore,
2324
# by leaving it empty we can ensure that the container and binary shipped on it will have the same platform.
24-
RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o manager cmd/main.go
25+
RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -ldflags "-w -s -X github.com/scaleway/cluster-api-provider-scaleway/internal/version.Version=${VERSION}" -o manager cmd/main.go
2526

2627
# Use distroless as minimal base image to package the manager binary
2728
# Refer to https://github.com/GoogleContainerTools/distroless for more details

Makefile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,18 @@ deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in
163163
undeploy: kustomize ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
164164
$(KUSTOMIZE) build config/default | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f -
165165

166+
##@ Release
167+
168+
.PHONY: release
169+
release: manifests generate kustomize ## Creates release manifests in "out" directory.
170+
mkdir -p out
171+
# building metadata.yaml
172+
cp metadata.yaml out/metadata.yaml
173+
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
174+
# building infrastructure-components.yaml
175+
$(KUSTOMIZE) build config/default > out/infrastructure-components.yaml
176+
# building templates
177+
cp templates/*.yaml out/
166178
##@ Dependencies
167179

168180
## Location to install dependencies to

cmd/main.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ package main
33
import (
44
"crypto/tls"
55
"flag"
6+
"fmt"
67
"os"
78
"path/filepath"
89

910
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
1011
// to ensure that exec-entrypoint and run can make use of them.
1112
_ "k8s.io/client-go/plugin/pkg/client/auth"
1213

14+
internalVersion "github.com/scaleway/cluster-api-provider-scaleway/internal/version"
1315
"k8s.io/apimachinery/pkg/runtime"
1416
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
1517
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
@@ -49,6 +51,7 @@ func main() {
4951
var probeAddr string
5052
var secureMetrics bool
5153
var enableHTTP2 bool
54+
var version bool
5255
var tlsOpts []func(*tls.Config)
5356
flag.StringVar(&metricsAddr, "metrics-bind-address", "0", "The address the metrics endpoint binds to. "+
5457
"Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.")
@@ -67,12 +70,19 @@ func main() {
6770
flag.StringVar(&metricsCertKey, "metrics-cert-key", "tls.key", "The name of the metrics server key file.")
6871
flag.BoolVar(&enableHTTP2, "enable-http2", false,
6972
"If set, HTTP/2 will be enabled for the metrics and webhook servers")
73+
flag.BoolVar(&version, "version", false,
74+
"If set, display version and exit")
7075
opts := zap.Options{
7176
Development: true,
7277
}
7378
opts.BindFlags(flag.CommandLine)
7479
flag.Parse()
7580

81+
if version {
82+
fmt.Println("cluster-api-provider-scaleway", internalVersion.Version)
83+
os.Exit(0)
84+
}
85+
7686
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))
7787

7888
// if the enable-http2 flag is false (the default), http/2 should be disabled

internal/service/scaleway/client/client.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"slices"
66

7+
"github.com/scaleway/cluster-api-provider-scaleway/internal/version"
78
"github.com/scaleway/scaleway-sdk-go/api/block/v1"
89
domain "github.com/scaleway/scaleway-sdk-go/api/domain/v2beta1"
910
"github.com/scaleway/scaleway-sdk-go/api/instance/v1"
@@ -20,6 +21,8 @@ const (
2021
createdByDescription = "Created by cluster-api-provider-scaleway"
2122
)
2223

24+
var userAgent = "cluster-api-provider-scaleway/" + version.Version
25+
2326
// Client is a wrapper over scaleway-sdk-go to access Scaleway Product APIs in
2427
// a specific region and project.
2528
type Client struct {
@@ -55,7 +58,7 @@ func New(region scw.Region, projectID string, secretData map[string][]byte) (*Cl
5558
scw.WithAuth(accessKey, secretKey),
5659
scw.WithDefaultProjectID(projectID),
5760
scw.WithDefaultRegion(region),
58-
scw.WithUserAgent("cluster-api-provider-scaleway/v0.0.0"), // TODO: set version.
61+
scw.WithUserAgent(userAgent),
5962
}
6063

6164
if apiURL := string(secretData[scw.ScwAPIURLEnv]); apiURL != "" {

internal/version/version.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package version
2+
3+
// Version is the version of cluster-api-provider-scaleway.
4+
// This variable should be set during build.
5+
var Version = "dev"

metadata.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# maps release series of major.minor to cluster-api contract version
2+
# the contract version may change between minor or major versions, but *not*
3+
# between patch versions.
4+
#
5+
# update this file only when a new major or minor version is released
6+
apiVersion: clusterctl.cluster.x-k8s.io/v1alpha3
7+
releaseSeries:
8+
- major: 0
9+
minor: 1
10+
contract: v1beta1

0 commit comments

Comments
 (0)