From c1ba312e312a72dbae7b589463dc2e5992f69013 Mon Sep 17 00:00:00 2001 From: amaslennikov Date: Tue, 17 Sep 2024 15:04:57 +0300 Subject: [PATCH] CI/CD pipeline Signed-off-by: amaslennikov --- .github/ISSUE_TEMPLATE/bug-report.md | 20 ++++++ .github/ISSUE_TEMPLATE/enhancement.md | 11 +++ .github/ISSUE_TEMPLATE/other.md | 13 ++++ .github/workflows/build-test-lint.yml | 86 +++++++++++++++++++++++ .github/workflows/chart-push-release.yaml | 28 ++++++++ .github/workflows/codeql.yml | 34 +++++++++ .github/workflows/image-push-main.yml | 49 +++++++++++++ .github/workflows/image-push-release.yml | 63 +++++++++++++++++ Makefile | 26 +++++++ hack/release/chart-push.sh | 35 +++++++++ hack/release/chart-update.sh | 36 ++++++++++ 11 files changed, 401 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug-report.md create mode 100644 .github/ISSUE_TEMPLATE/enhancement.md create mode 100644 .github/ISSUE_TEMPLATE/other.md create mode 100644 .github/workflows/build-test-lint.yml create mode 100644 .github/workflows/chart-push-release.yaml create mode 100644 .github/workflows/codeql.yml create mode 100644 .github/workflows/image-push-main.yml create mode 100644 .github/workflows/image-push-release.yml create mode 100755 hack/release/chart-push.sh create mode 100755 hack/release/chart-update.sh diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md new file mode 100644 index 0000000..2356ade --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -0,0 +1,20 @@ +--- +name: Bug Report +about: Report a bug for the project + +--- + + +### What happened? + +### What did you expect to happen? + +### What are the minimal steps needed to reproduce the bug? + +### Anything else we need to know? + +### Component Versions + +### Logs +##### Nic Configuration Operator Logs (use `kubectl logs $PODNAME`) +##### Nic Configuration Daemon Logs (use `kubectl logs $PODNAME`) diff --git a/.github/ISSUE_TEMPLATE/enhancement.md b/.github/ISSUE_TEMPLATE/enhancement.md new file mode 100644 index 0000000..7fb46a5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/enhancement.md @@ -0,0 +1,11 @@ +--- +name: Enhancement / Feature Request +about: Suggest an enhancement or new feature for the project + +--- + + + +## What would you like to be added? + +## What is the use case for this feature / enhancement? diff --git a/.github/ISSUE_TEMPLATE/other.md b/.github/ISSUE_TEMPLATE/other.md new file mode 100644 index 0000000..c7fbf28 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/other.md @@ -0,0 +1,13 @@ +--- +name: Other Issues +about: For everything that isn't a bug report or a feature request + +--- + + + +## What issue would you like to bring attention to? + +## What is the impact of this issue? + +## Do you have a proposed response or remediation for the issue? diff --git a/.github/workflows/build-test-lint.yml b/.github/workflows/build-test-lint.yml new file mode 100644 index 0000000..2db44d0 --- /dev/null +++ b/.github/workflows/build-test-lint.yml @@ -0,0 +1,86 @@ +name: "Build, Test, Lint" +on: [push, pull_request] +jobs: + build: + strategy: + matrix: + go-version: [1.22.x] + goarch: [amd64] + os: [ubuntu-latest] + runs-on: ${{ matrix.os }} + steps: + - name: Set up Go matrix + uses: actions/setup-go@v5 + with: + go-version: ${{ matrix.go-version }} + - name: Check out code into the Go module directory + uses: actions/checkout@v4 + - name: Build + env: + GOARCH: ${{ matrix.goarch }} + GOOS: ${{ matrix.goos }} + run: make build + lint: + runs-on: ubuntu-latest + needs: build + steps: + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: 1.22.x + - name: Check out code into the Go module directory + uses: actions/checkout@v4 + - name: Lint + run: make lint + test: + runs-on: ubuntu-latest + needs: build + steps: + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: 1.22.x + - name: Check out code into the Go module directory + uses: actions/checkout@v4 + - name: Run tests + run: make test + build-image: + runs-on: ubuntu-latest + steps: + - name: Check out code into the Go module directory + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Build image + run: make docker-build + go-check: + runs-on: ubuntu-latest + needs: build + steps: + - uses: actions/checkout@v4 + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: 1.22.x + # if this fails, run go mod tidy + - name: Check if module files are consistent with code + run: go mod tidy && git diff --exit-code + # if this fails, run make generate; make manifests and commit changes + - name: Check if generated are up to date + run: make generate && make manifests && git diff --exit-code + coverage: + runs-on: ubuntu-latest + needs: build + steps: + - uses: actions/checkout@v4 + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: 1.22.x + - name: Generate coverage report + run: make test + - name: Upload to Coveralls + uses: coverallsapp/github-action@v2 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + file: cover.out diff --git a/.github/workflows/chart-push-release.yaml b/.github/workflows/chart-push-release.yaml new file mode 100644 index 0000000..dd62d47 --- /dev/null +++ b/.github/workflows/chart-push-release.yaml @@ -0,0 +1,28 @@ +name: "Push helm chart on release" + +env: + IMAGE_NAME: ghcr.io/${{ github.repository }} + +on: + push: + tags: + - v* +jobs: + package-and-push-helm-chart: + runs-on: ubuntu-22.04 + steps: + - name: Check out the repo + uses: actions/checkout@v4 + + - name: Update chart + env: + GITHUB_TAG: ${{ github.ref_name }} + GITHUB_REPO_OWNER: ${{ github.repository_owner }} + run: make chart-prepare-release + + - name: Push chart + env: + GITHUB_TAG: ${{ github.ref_name }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_REPO_OWNER: ${{ github.repository_owner }} + run: make chart-push-release diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..554998e --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,34 @@ +name: "CodeQL" +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + schedule: + - cron: "37 4 * * 0" +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + strategy: + fail-fast: false + matrix: + language: [go] + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + queries: +security-and-quality + - name: Autobuild + uses: github/codeql-action/autobuild@v3 + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{ matrix.language }}" diff --git a/.github/workflows/image-push-main.yml b/.github/workflows/image-push-main.yml new file mode 100644 index 0000000..168921a --- /dev/null +++ b/.github/workflows/image-push-main.yml @@ -0,0 +1,49 @@ +name: "Image push main" +on: + push: + branches: + - main +jobs: + image-build-push: + name: Image build and push + runs-on: ubuntu-latest + steps: + - name: Set repository as lower-case output variable + id: repo_name + run: echo ::set-output name=repository::$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]') + - name: Check out code into the Go module directory + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Docker meta + id: docker_meta + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ steps.repo_name.outputs.repository }} + - name: Build and push container image + uses: docker/build-push-action@v4 + with: + push: true + platforms: linux/amd64,linux/arm64 + tags: | + ghcr.io/${{ steps.repo_name.outputs.repository }}:latest + labels: ${{ steps.docker_meta.outputs.labels }} + - name: Build and push container image + uses: docker/build-push-action@v4 + with: + push: true + platforms: linux/amd64,linux/arm64 + tags: | + ghcr.io/${{ steps.repo_name.outputs.repository }}-daemon:latest + labels: ${{ steps.docker_meta.outputs.labels }} + file: ./Dockerfile.nic-configuration-daemon diff --git a/.github/workflows/image-push-release.yml b/.github/workflows/image-push-release.yml new file mode 100644 index 0000000..09ea363 --- /dev/null +++ b/.github/workflows/image-push-release.yml @@ -0,0 +1,63 @@ +name: "Image push release" +on: + push: + tags: + - v* +jobs: + image-build-push: + name: Image build and push + runs-on: ubuntu-latest + steps: + - name: Set repository as lower-case output variable + id: repo_name + run: echo ::set-output name=repository::$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]') + - name: Check out code into the Go module directory + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Docker operator image meta + id: docker_meta_operator + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ steps.repo_name.outputs.repository }} + tags: | + type=ref,event=tag + flavor: | + latest=false + - name: Build and push operator image + uses: docker/build-push-action@v4 + with: + platforms: linux/amd64,linux/arm64 + push: true + tags: | + ${{ steps.docker_meta_operator.outputs.tags }} + labels: ${{ steps.docker_meta_operator.outputs.labels }} + - name: Docker daemon image meta + id: docker_meta_daemon + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ steps.repo_name.outputs.repository }}-daemon + tags: | + type=ref,event=tag + flavor: | + latest=false + - name: Build and push config daemon image + uses: docker/build-push-action@v4 + with: + platforms: linux/amd64,linux/arm64 + push: true + tags: | + ${{ steps.docker_meta_daemon.outputs.tags }} + labels: ${{ steps.docker_meta_daemon.outputs.labels }} + file: ./Dockerfile + diff --git a/Makefile b/Makefile index f95e792..6185d5f 100644 --- a/Makefile +++ b/Makefile @@ -251,6 +251,24 @@ envtest: $(ENVTEST) ## Download setup-envtest locally if necessary. $(ENVTEST): $(LOCALBIN) $(call go-install-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest,$(ENVTEST_VERSION)) +YQ := $(abspath $(LOCALBIN)/yq) +YQ_VERSION=v4.44.1 +.PHONY: yq +yq: $(YQ) ## Download yq locally if necessary. +$(YQ): | $(LOCALBIN) + @curl -fsSL -o $(YQ) https://github.com/mikefarah/yq/releases/download/$(YQ_VERSION)/yq_linux_amd64 && chmod +x $(YQ) + +HELM := $(abspath $(LOCALBIN)/helm) +.PHONY: helm +helm: $(HELM) ## Download helm (last release) locally if necessary. +$(HELM): | $(LOCALBIN) + @{ \ + curl -fsSL -o $(LOCALBIN)/get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 && \ + chmod 700 $(LOCALBIN)/get_helm.sh && \ + HELM_INSTALL_DIR=$(LOCALBIN) USE_SUDO=false $(LOCALBIN)/get_helm.sh && \ + rm -f $(LOCALBIN)/get_helm.sh; \ + } + .PHONY: golangci-lint golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary. $(GOLANGCI_LINT): $(LOCALBIN) @@ -342,3 +360,11 @@ catalog-build: opm ## Build a catalog image. .PHONY: catalog-push catalog-push: ## Push a catalog image. $(MAKE) docker-push IMG=$(CATALOG_IMG) + +.PHONY: chart-prepare-release +chart-prepare-release: | $(YQ) ## prepare helm chart for release + @GITHUB_TAG=$(GITHUB_TAG) GITHUB_REPO_OWNER=$(GITHUB_REPO_OWNER) hack/release/chart-update.sh + +.PHONY: chart-push-release +chart-push-release: | $(HELM) ## push release helm chart + @GITHUB_TAG=$(GITHUB_TAG) GITHUB_TOKEN=$(GITHUB_TOKEN) GITHUB_REPO_OWNER=$(GITHUB_REPO_OWNER) hack/release/chart-push.sh diff --git a/hack/release/chart-push.sh b/hack/release/chart-push.sh new file mode 100755 index 0000000..393752b --- /dev/null +++ b/hack/release/chart-push.sh @@ -0,0 +1,35 @@ +#!/bin/bash +set -ex + +# github repo owner: e.g mellanox +GITHUB_REPO_OWNER=${GITHUB_REPO_OWNER:-} +# github api token with package:write permissions +GITHUB_TOKEN=${GITHUB_TOKEN:-} +# github tag e.g v1.2.3 +GITHUB_TAG=${GITHUB_TAG:-} + +BASE=${PWD} +HELM_CMD="${BASE}/bin/helm" +HELM_CHART=${BASE}/deployment/nic-configuration-operator-chart +HELM_CHART_VERSION=${GITHUB_TAG#"v"} +HELM_CHART_TARBALL="nic-configuration-operator-chart-${HELM_CHART_VERSION}.tgz" + +if [ -z "$GITHUB_REPO_OWNER" ]; then + echo "ERROR: GITHUB_REPO_OWNER must be provided as env var" + exit 1 +fi + +if [ -z "$GITHUB_TOKEN" ]; then + echo "ERROR: GITHUB_TOKEN must be provided as env var" + exit 1 +fi + +if [ -z "$GITHUB_TAG" ]; then + echo "ERROR: GITHUB_TAG must be provided as env var" + exit 1 +fi + +$HELM_CMD package ${HELM_CHART} +$HELM_CMD registry login ghcr.io -u ${GITHUB_REPO_OWNER} -p ${GITHUB_TOKEN} +# we set repo-owner to lowercase for oci registry. +$HELM_CMD push ${HELM_CHART_TARBALL} oci://ghcr.io/$(echo ${GITHUB_REPO_OWNER} | tr '[:upper:]' '[:lower:]') diff --git a/hack/release/chart-update.sh b/hack/release/chart-update.sh new file mode 100755 index 0000000..e0a7c9d --- /dev/null +++ b/hack/release/chart-update.sh @@ -0,0 +1,36 @@ +#!/bin/bash +set -ex + +# github tag e.g v1.2.3 +GITHUB_TAG=${GITHUB_TAG:-} +# github repo owner e.g Mellanox +GITHUB_REPO_OWNER=${GITHUB_REPO_OWNER:-} + +BASE=${PWD} +YQ_CMD="${BASE}/bin/yq" +HELM_VALUES=${BASE}/deployment/nic-configuration-operator-chart/values.yaml +HELM_CHART=${BASE}/deployment/nic-configuration-operator-chart/Chart.yaml + + +if [ -z "$GITHUB_TAG" ]; then + echo "ERROR: GITHUB_TAG must be provided as env var" + exit 1 +fi + +if [ -z "$GITHUB_REPO_OWNER" ]; then + echo "ERROR: GITHUB_REPO_OWNER must be provided as env var" + exit 1 +fi + +# tag provided via env var +OPERATOR_TAG=${GITHUB_TAG} + +# patch values.yaml in-place + +# maintenance-operator image: +OPERATOR_REPO=$(echo ${GITHUB_REPO_OWNER} | tr '[:upper:]' '[:lower:]') # this is used to allow to release maintenance-operator from forks +$YQ_CMD -i ".operator.image.repository = \"ghcr.io/${OPERATOR_REPO}/nic-configuration-operator\"" ${HELM_VALUES} + +# patch Chart.yaml in-place +$YQ_CMD -i ".version = \"${OPERATOR_TAG#"v"}\"" ${HELM_CHART} +$YQ_CMD -i ".appVersion = \"${OPERATOR_TAG}\"" ${HELM_CHART}