diff --git a/.github/workflows/go_app_pull_requests.yml b/.github/workflows/go_app_pull_requests.yml new file mode 100644 index 0000000..5276e9d --- /dev/null +++ b/.github/workflows/go_app_pull_requests.yml @@ -0,0 +1,121 @@ +name: Pull Request + +on: + workflow_call: + inputs: + GH_CI_USER: + description: 'User for GitHub auth' + required: true + type: string + GOPRIVATE: + description: 'GOPRIVATE env for go commands' + required: false + type: string + secrets: + GH_CI_PAT: + description: 'Token password for GitHub auth' + required: true + +env: + GOPRIVATE: ${{ inputs.GOPRIVATE }} + +jobs: + commitlint: + # + # ensures commit messages follow conventional commits + # + runs-on: ubuntu-latest + steps: + # checkout the commits to lint. + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + # setup node, needed to lint commits. + - uses: actions/setup-node@v1 + with: + node-version: 14 + # Install needed libraries to lint commits. + - run: npm install --save-dev @commitlint/{config-conventional,cli} + # Lint the commits. + - run: npx commitlint --from=${{ github.event.pull_request.base.sha }} + + test: + # + # ensure go standards and tests pass + # + runs-on: ubuntu-latest + strategy: + matrix: + # List of go versions to test on. + go: ['^1.16', '^1.17', '^1'] + steps: + # Checkout go code to test. + - name: Checkout repo + uses: actions/checkout@v2 + # Setup Go for each version in the matrix. + - name: Setup Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go }} + # Use auth to get access to private Git repos for Go code dependencies. + - name: Configure git for private modules + env: + TOKEN: ${{ secrets.GH_CI_PAT }} + GITHUB_USERNAME: ${{ inputs.GH_CI_USER }} + run: git config --global url."https://${GITHUB_USERNAME}:${TOKEN}@github.com".insteadOf "https://github.com" + # Vendor Go code for ever Go module. + - name: go mod vendor + run: find . -name vendor -prune -o -name go.mod -print | xargs -n1 dirname | xargs -n1 -I{} bash -c "pushd {}; go mod vendor" + # Go vet every Go module. + - name: go vet + run: find . -name vendor -prune -o -name go.mod -print | xargs -n1 dirname | xargs -n1 -I{} bash -c "pushd {}; go vet ./..." + # Run unit test for evet Go module. + - name: go test + run: find . -name vendor -prune -o -name go.mod -print | xargs -n1 dirname | xargs -n1 -I{} bash -c "pushd {}; go test -mod=vendor --race -v ./..." + + docker-build: + # + # ensures the docker image will build without pushing to the registry + # uses the git sha for the most recent commit for the version + # + runs-on: ubuntu-latest + steps: + # Checkout code to build. + - name: Checkout repo + uses: actions/checkout@v2 + # Setup Go in order to vendor dependencies in a later step. + - name: Setup Go + uses: actions/setup-go@v2 + with: + go-version: '^1' + # Use auth to get access to private Git repos for Go code dependencies. + - name: Configure git for private modules + env: + TOKEN: ${{ secrets.GH_CI_PAT }} + GITHUB_USERNAME: ${{ inputs.GH_CI_USER }} + run: git config --global url."https://${GITHUB_USERNAME}:${TOKEN}@github.com".insteadOf "https://github.com" + # Vendor Go code needed to build app. + - name: go mod vendor + run: go mod vendor + # Setup docker build arguments. + - name: Docker release meta + id: release + uses: docker/metadata-action@v3 + with: + images: | + ${{ github.repository }} + tags: | + type=sha + # Setup Docker builder to do build. + - name: Setup Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v1 + # Build the app. + - name: Build + uses: docker/build-push-action@v2 + with: + push: false + context: . + file: Dockerfile + platforms: linux/amd64 + tags: ${{ steps.release.outputs.tags }} diff --git a/.github/workflows/go_app_push_main.yml b/.github/workflows/go_app_push_main.yml new file mode 100644 index 0000000..8cdda8d --- /dev/null +++ b/.github/workflows/go_app_push_main.yml @@ -0,0 +1,39 @@ +name: Create Github Release + +on: + workflow_call: + secrets: + GH_CI_PAT: + description: 'Token password for GitHub auth' + required: true + +jobs: + release: + # + # Create a GitHub Release based on conventional commits. + # + name: 'Release to GitHub' + runs-on: ubuntu-latest + steps: + # Checkout code to release. + - name: Checkout repo + uses: actions/checkout@v2 + # Setup Node needed to create release. + - name: Setup Node.js + uses: actions/setup-node@v1 + with: + node-version: 14 + # Add plugin to make the changelog for the release. + - name: Add plugin for conventional commits + run: npm install conventional-changelog-conventionalcommits + working-directory: ./.github/workflows + # Create the release. + - name: Release to GitHub + working-directory: ./.github/workflows + env: + GITHUB_TOKEN: ${{ secrets.GH_CI_PAT }} + GIT_AUTHOR_NAME: release-bot + GIT_AUTHOR_EMAIL: release@test.com + GIT_COMMITTER_NAME: asyncapi-bot + GIT_COMMITTER_EMAIL: info@asyncapi.io + run: npx semantic-release diff --git a/.github/workflows/go_app_release.yml b/.github/workflows/go_app_release.yml new file mode 100644 index 0000000..310b49e --- /dev/null +++ b/.github/workflows/go_app_release.yml @@ -0,0 +1,135 @@ +name: Release Docker Version + +on: + workflow_call: + inputs: + GH_CI_USER: + description: 'User for GitHub auth' + required: true + type: string + GOPRIVATE: + description: 'GOPRIVATE env for go commands' + required: false + type: string + secrets: + GH_CI_PAT: + description: 'Token password for GitHub auth' + required: true + + # Registry arguments. + # Must supply set of arguments for at least 1 registry. + + # Artifact Registry arguments + ARTIFACT_REGISTRY: + description: 'Artifact Registry address to which to publish (leave blank to not publish)' + required: false + ARTIFACT_REGISTRY_JSON_KEY: + description: 'Key for publishing to Artifact Registry' + required: false + # Container Registry arguements + CONTAINER_REGISTRY: + description: 'Container Registry address to which to publish (leave blank to not publish)' + required: false + CONTAINER_REGISTRY_JSON_KEY: + description: 'Key for publishing to Container Registry' + required: false + +env: + GOPRIVATE: ${{ inputs.GOPRIVATE }} + +jobs: + push: + # + # Build the Docker image artifact and deliver it. + # + runs-on: ubuntu-latest + steps: + # Checkout code needed to build docker image. + - uses: actions/checkout@v2 + # Setup Go in order to vendor dependencies in a later setp. + - name: Setup Go + uses: actions/setup-go@v2 + with: + go-version: '^1' + # Use auth to get access to private Git repos for Go code dependencies. + - name: Configure git for private modules + env: + TOKEN: ${{ secrets.GH_CI_PAT }} + GITHUB_USERNAME: ${{ inputs.GH_CI_USER }} + run: git config --global url."https://${GITHUB_USERNAME}:${TOKEN}@github.com".insteadOf "https://github.com" + # Vendor Go code needed to build docker image. + - name: go mod vendor + run: go mod vendor + # Parse GitHub repository name for use in constructing docker image names. + - name: Parse Repo Name + id: parse_repo_name + run: | + echo ::set-output name=repo_name::"$( echo '${{ github.repository }}' | awk -F '/' '{print $2}' )" + # Make the docker fields for Artifact Registry if we're pushing to it. + - name: Construct Artifact Registry fields + env: + ARTIFACT_REGISTRY: ${{ secrets.ARTIFACT_REGISTRY }} + if: ${{ env.ARTIFACT_REGISTRY }} + run: | + echo "ARTIFACT_REGISTRY_IMAGE_NAME=${{ secrets.ARTIFACT_REGISTRY }}/${{ github.repository }}" >> $GITHUB_ENV + echo "ARTIFACT_REGISTRY_DOMAIN=$(echo "${{ secrets.ARTIFACT_REGISTRY }}" | sed -e 's|^[^/]*//||' -e 's|/.*$||')" >> $GITHUB_ENV + # Make the docker fields for Container Registry if we're pushing to it. + - name: Construct Container Registry fields + env: + CONTAINER_REGISTRY: ${{ secrets.CONTAINER_REGISTRY }} + if: ${{ env.CONTAINER_REGISTRY }} + run: | + echo "CONTAINER_REGISTRY_IMAGE_NAME=${{ secrets.CONTAINER_REGISTRY }}/${{ steps.parse_repo_name.outputs.repo_name }}" >> $GITHUB_ENV + echo "CONTAINER_REGISTRY_DOMAIN=$(echo "${{ secrets.CONTAINER_REGISTRY }}" | sed -e 's|^[^/]*//||' -e 's|/.*$||')" >> $GITHUB_ENV + # Create docker image meta data. Docker tags include the Git tag itself and the sematic version parsing of that tag if possible. + - name: Docker release meta + id: release + uses: docker/metadata-action@v3 + with: + images: | + ${{ env.ARTIFACT_REGISTRY_IMAGE_NAME }} + ${{ env.CONTAINER_REGISTRY_IMAGE_NAME }} + flavor: | + latest=false + tags: | + type=ref,event=tag + type=semver,pattern={{version}} + # Login to Artifact Registry if we're pushing to it. + - name: Login to Artifact Registry + env: + ARTIFACT_REGISTRY_JSON_KEY: ${{ secrets.ARTIFACT_REGISTRY_JSON_KEY }} + if: ${{ env.ARTIFACT_REGISTRY_JSON_KEY }} + uses: docker/login-action@v1 + with: + registry: ${{ env.ARTIFACT_REGISTRY_DOMAIN }} + username: _json_key + password: ${{ secrets.ARTIFACT_REGISTRY_JSON_KEY }} + # Login to Container Registry if we're pushing to it. + - name: Login to Container Registry + env: + CONTAINER_REGISTRY_JSON_KEY: ${{ secrets.CONTAINER_REGISTRY_JSON_KEY }} + if: ${{ env.CONTAINER_REGISTRY_JSON_KEY }} + uses: docker/login-action@v1 + with: + registry: ${{ env.CONTAINER_REGISTRY_DOMAIN }} + username: _json_key + password: ${{ secrets.CONTAINER_REGISTRY_JSON_KEY }} + # Setup QEMU needed to build arm64 images. + - name: Setup QEMU + uses: docker/setup-qemu-action@v1 + # Setup Docker builder needed to build multi-architectural images. + - name: Setup Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v1 + # Build and push the image. + - name: Build and Push to Artifact Registry and Container Registry + uses: docker/build-push-action@v2 + with: + push: true + context: . + file: Dockerfile + platforms: linux/amd64,linux/arm64 + build-args: | + VERSION=${{ steps.release.outputs.version }} + tags: ${{ steps.release.outputs.tags }} + labels: ${{ steps.release.outputs.labels }} diff --git a/README.md b/README.md index 44d5f03..a6c8e7e 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,30 @@ -# github-workflows -Github Action Workflows +# Kochava Github Action Workflows + +This repo contains GitHub Action Workflow Templates for Kochava's various workflows + +## Workflow Types + +| Workflow Type | File Prefix | Tag Format | Description | +|---------------|-------------|------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Go App | go_app | go/app/{version} | Used for Go application projects intended to be deployed as a Docker image. Tests/Lints on PRs, Creates a Release based on conventional commits when merged to main, Publishes Docker image on Release. | + +## Versioning + +In order to protect workflow users from having their workflows break, we must carefully consider versioning. Tags should be prefixed by a workflow type. + +- example: `go/app/v1.0.0` + +This will allow repositories that use this templates to choose tags accordingly and know when there might be breaking changes with the way they use the worklflow by checking the major version. + +There should also be tags that are updated after every update to a major version. + +- example: `go/app/v1` + +This will allow users to specify a major version and always be up to date with minor updates. + +As such, whenever changes are made to workflow templates and a tag is to be created, the major version should increment if there are any major changes to a workflow. This is up to the discresion of the person making the tag, but some possible reasons to increment the major version include but are not limited to: + - major behavior for a workflow is changed in a way that will no longer satisfy a user of that template + * example: no longer publishing a docker image to a place it would have published before with the same inputs. + * exeption example: adding a `go vet` step to the go app workflows since we may want to enforce all workflows that fail this to immediately fix their code. + - an input/secret/output is removed + - possible input/secret values that worked before will no longer work or result in different intended behavior.