From 943ab28d10fa17146a225b9b3758f84e257c15ad Mon Sep 17 00:00:00 2001 From: Nick Neisen Date: Fri, 3 Nov 2023 15:44:30 -0600 Subject: [PATCH] [BOP-56] Run CI on merge to main (#8) * Run CI on merge * Add the dev tag * Update workflow title docs --- .github/development.env | 4 ++ .github/workflows/Merge.yml | 18 +++++ .github/workflows/README.md | 11 +-- .github/workflows/build.yml | 21 ++++-- .github/workflows/push-to-ghcr.yml | 109 +++++++++++++++++++++++++++++ .github/workflows/release.yml | 27 ------- docs/CI.md | 22 ++++++ 7 files changed, 176 insertions(+), 36 deletions(-) create mode 100644 .github/workflows/Merge.yml create mode 100644 .github/workflows/push-to-ghcr.yml delete mode 100644 .github/workflows/release.yml create mode 100644 docs/CI.md diff --git a/.github/development.env b/.github/development.env index f20dcf72..9b9a9748 100644 --- a/.github/development.env +++ b/.github/development.env @@ -1,3 +1,7 @@ GO_VERSION=1.21.3 UNIT_TEST_SCOPE=./cmd/... ./pkg/... + +REGISTRY=ghcr.io +ORG=mirantis +IMAGE=boundless-operator diff --git a/.github/workflows/Merge.yml b/.github/workflows/Merge.yml new file mode 100644 index 00000000..2cc74e7a --- /dev/null +++ b/.github/workflows/Merge.yml @@ -0,0 +1,18 @@ +name: Merge + +on: + push: + branches: + - main + +jobs: + vet: + uses: ./.github/workflows/vet.yml + unit-test: + uses: ./.github/workflows/unit.yml + build: + uses: ./.github/workflows/build.yml + push-to-ghcr: + if: ${{ always() && contains(join(needs.*.result, ','), 'success') }} # if all need jobs are successful + needs: [vet, unit-test, build] + uses: ./.github/workflows/push-to-ghcr.yml diff --git a/.github/workflows/README.md b/.github/workflows/README.md index ff9f4db3..72285727 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -1,11 +1,14 @@ # Workflows -There are two types of workflows in this directory. I would put them in subfolders but GitHub doesn't support that. +There are two types of workflows in this directory. I would put them in subfolders but GitHub doesn't support that. Since we can't use folders, capital letters are used for the "Caller" workflows and lowercase for the "Job" workflows. This is just a convention to help keep track of what is what. ## Callers -These are the high level workflows that can be associated with what triggers them. PRs, releases, nightlys, merges, etc. These are made up of jobs that are defined the the other workflows. These are the workflows that you will see in the Actions tab of the repo. By grouping these tasks into parent workflows, the jobs are grouped under one action in the actions tab. They share the smaller 'job' workflows so that they always run the same way. Convention has become to capitalize the first letter of these workflow's name. - +These are the high level workflows that can be associated with what triggers them. PRs, releases, nightlys, merges, etc. These are made up of jobs that are defined the the other workflows. These are the workflows that you will see in the Actions tab of the repo. By grouping these tasks into parent workflows, the jobs are grouped under one action in the actions tab. They share the smaller 'job' workflows so that they always run the same way. ## Jobs -These are the smaller individual tasks that are used to build up the larger parent workflows. They can be thought of as running unit tests, building the binaries, or linting the code. When you open one of the parent caller actions in the actions tab, they will show these individual jobs. Convention has become to lowercase the first letter of these workflow's name. +These are the smaller individual tasks that are used to build up the larger parent workflows. They can be thought of as running unit tests, building the binaries, or linting the code. When you open one of the parent caller actions in the actions tab, they will show these individual jobs. + +# Working with workflows + +The easiest way to test a workflow is by creating it on your forked repo. This way you have control over the settings and you can manipulate branches anyway you need to trigger the workflow. When testing this way, you should be careful that you are pushing to your repo and not the company's and also make sure to clean everything up in your repo once you have finished testing. diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 767ba916..865052b9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,13 +10,24 @@ jobs: - name: Checkout uses: actions/checkout@v3 - - name: Log in to the Container registry - uses: docker/login-action@v3.0.0 + - name: Load environment + uses: c-py/action-dotenv-to-setenv@v4 with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + env-file: .github/development.env - name: Build docker image working-directory: . run: make docker-build + + - name: Save docker image + if: ${{ github.event_name == 'release' || github.event_name == 'push'}} # release or push to main + working-directory: . + run: docker save ${{ env.REGISTRY }}/${{ env.ORG }}/${{ env.IMAGE }}:latest -o /tmp/${{ env.IMAGE }}.tar + + - name: Upload docker image + if: ${{ github.event_name == 'release' || github.event_name == 'push'}} # release or push to main + uses: actions/upload-artifact@v3 + with: + name: ${{ env.IMAGE }} + retention-days: 1 + path: /tmp/${{ env.IMAGE }}.tar diff --git a/.github/workflows/push-to-ghcr.yml b/.github/workflows/push-to-ghcr.yml new file mode 100644 index 00000000..118d917f --- /dev/null +++ b/.github/workflows/push-to-ghcr.yml @@ -0,0 +1,109 @@ +name: Push docker images + +on: + workflow_call: + +jobs: + # push-latest: + # runs-on: ubuntu-latest + # steps: + # - name: Checkout + # uses: actions/checkout@v3 + + # - name: Load environment + # uses: c-py/action-dotenv-to-setenv@v4 + # with: + # env-file: .github/development.env + + # - name: Log in to the Container registry + # uses: docker/login-action@v3.0.0 + # with: + # registry: ${{ env.REGISTRY }} + # username: ${{ github.actor }} + # password: ${{ secrets.GITHUB_TOKEN }} + + # - name: Download artifact + # uses: actions/download-artifact@v3 + # with: + # name: ${{ env.IMAGE }} + # path: /tmp + + # - name: Load docker image + # working-directory: . + # run: docker load --input /tmp/${{ env.IMAGE }}.tar + + # - name: Push latest image to ${{ env.REGISTRY }} + # working-directory: . + # run: make docker-push + + push-sha: + if: ${{ github.event_name == 'push' }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Load environment + uses: c-py/action-dotenv-to-setenv@v4 + with: + env-file: .github/development.env + + - name: Log in to the Container registry + uses: docker/login-action@v3.0.0 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Download artifact + uses: actions/download-artifact@v3 + with: + name: ${{ env.IMAGE }} + path: /tmp + + - name: Load docker image + working-directory: . + run: docker load --input /tmp/${{ env.IMAGE }}.tar + + - name: Push SHA image to ${{ env.REGISTRY }} + working-directory: . + run: | + COMMIT_SHA=$(git rev-parse --short "$GITHUB_SHA") + echo $COMMIT_SHA + docker tag ${{ env.REGISTRY }}/${{ env.ORG }}/${{ env.IMAGE }}:latest ${{ env.REGISTRY }}/${{ env.ORG }}/${{ env.IMAGE }}:$COMMIT_SHA + docker push ${{ env.REGISTRY }}/${{ env.ORG }}/${{ env.IMAGE }}:$COMMIT_SHA + + push-dev: + if: ${{ github.event_name == 'push' }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Load environment + uses: c-py/action-dotenv-to-setenv@v4 + with: + env-file: .github/development.env + + - name: Log in to the Container registry + uses: docker/login-action@v3.0.0 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Download artifact + uses: actions/download-artifact@v3 + with: + name: ${{ env.IMAGE }} + path: /tmp + + - name: Load docker image + working-directory: . + run: docker load --input /tmp/${{ env.IMAGE }}.tar + + - name: Push SHA image to ${{ env.REGISTRY }} + working-directory: . + run: | + docker tag ${{ env.REGISTRY }}/${{ env.ORG }}/${{ env.IMAGE }}:latest ${{ env.REGISTRY }}/${{ env.ORG }}/${{ env.IMAGE }}:dev + docker push ${{ env.REGISTRY }}/${{ env.ORG }}/${{ env.IMAGE }}:dev diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 6869fe2b..00000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Build and Push Docker Image - -on: - push: - branches: [ "main" ] - -jobs: - build-and-push: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Log in to the Container registry - uses: docker/login-action@v3.0.0 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Build docker image - working-directory: . - run: make docker-build - - - name: Push docker image to ghcr.io - working-directory: . - run: make docker-push diff --git a/docs/CI.md b/docs/CI.md new file mode 100644 index 00000000..641eb97e --- /dev/null +++ b/docs/CI.md @@ -0,0 +1,22 @@ +# CI + +This document describes the CI/CD pipeline for the project. This document is for those developing on the project to understand everything that is running when they make a change to the code. If you are interested in modifying the CI/CD pipeline, see [README](.github/workflows/README.md) in the workflows directory. + +## PRs + +CI for a PR will trigger whenever a PR is opened, reopened, or pushed. The jobs ran on a PR are meant to be lightweight enough that we can repeatedly run them (each push) but cover enough of the code that we don't have to create a followup PR to fix things that we've missed. The image will not be pushed to the registry after a successful PR run. The jobs ran on a PR are: + +- 'vet' - Check the code changes and make sure they adhere to the standard Golang style guide +- 'test' - Run the unit tests on the code changes +- 'build' - Build an image containing the code changes + +## Merging to main + +Merging to main runs many of the same tests as a PR to verify that merging the code didn't introduce any new issues. Merging will also run integration tests to verify that the code works with the rest of the system as these tests require more setup and take longer to run. After all of the steps successfully run, the same image will be pushed with the commit `sha` and `dev` tags. + +TODO: code coverage +TODO: If you merge a change into main and an issue is found, you will be notified on slack that you have broken main and need to fix it. + +## Releases + +A release is triggered when a pre-release is created in the github repo. This will run EVERYTHING from scratch. Starting from zero may take more time but this ensures that nothing slips by us before sending out the release. This includes any static code analysis, unit tests, integration tests, and building the binaries. If everything passes, the same image will pushed with `latest`, `sha`, `semver`, and `dev` tags.