From e64b36ebcf8f7891c162e7822332cd5871356238 Mon Sep 17 00:00:00 2001
From: Pamme Crandall
Date: Mon, 18 Jul 2022 16:55:00 -0600
Subject: [PATCH] Creates a draft github release on a release branch and pushes
the docker image to github container registry on a release tag.
---
.github/release.yml | 26 +++++++
.github/workflows/ci.yml | 32 +++++++--
.github/workflows/release.yaml | 125 +++++++++++++++++++++++++++++++++
3 files changed, 178 insertions(+), 5 deletions(-)
create mode 100644 .github/release.yml
create mode 100644 .github/workflows/release.yaml
diff --git a/.github/release.yml b/.github/release.yml
new file mode 100644
index 0000000000..191ccd628f
--- /dev/null
+++ b/.github/release.yml
@@ -0,0 +1,26 @@
+changelog:
+ exclude:
+ labels:
+ - skip-changelog
+ categories:
+ - title: ๐ Features
+ labels:
+ - enhancement
+ - title: ๐ฃ Breaking Changes
+ labels:
+ - change
+ - title: ๐ Bug Fixes
+ labels:
+ - bug
+ - title: ๐ Documentation
+ labels:
+ - documentation
+ - title: ๐งช Tests
+ labels:
+ - tests
+ - title: ๐จ Maintenance
+ labels:
+ - chore
+ - title: โฌ๏ธ Dependencies
+ labels:
+ - dependencies
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index c365e8cc7e..354bde9b1b 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -3,9 +3,10 @@ name: Continuous Integration
on:
push:
branches:
- - 'main'
+ - main
+ - release-*
tags:
- - 'v[0-9]+.[0-9]+.[0-9]+'
+ - 'v[0-9]+.[0-9]+.[0-9]+*'
paths-ignore:
- '**.md'
pull_request:
@@ -119,16 +120,37 @@ jobs:
key: nginx-kubernetes-gateway-${{ github.run_id }}-${{ github.run_number }}
- name: Docker Buildx
uses: docker/setup-buildx-action@v2
+ - name: Login to GitHub Container Registry
+ uses: docker/login-action@v2
+ if: ${{ startsWith(github.ref, 'refs/tags') }}
+ with:
+ registry: ghcr.io
+ username: ${{ github.repository_owner }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+ - name: Docker meta
+ id: meta
+ uses: docker/metadata-action@v4
+ with:
+ images: |
+ name=ghcr.io/nginxinc/nginx-kubernetes-gateway
+ tags: |
+ type=semver,pattern={{version}}
+ type=edge
+ type=ref,event=pr
+ type=ref,event=branch,enable=${{ startsWith(github.ref, 'refs/heads/release') }}
+ flavor: |
+ latest=true
- name: Build Image Debian
uses: docker/build-push-action@v3
with:
file: build/Dockerfile
context: '.'
target: local
- load: true
+ tags: ${{ steps.meta.outputs.tags }}
+ load: ${{ !startsWith(github.ref, 'refs/tags') }}
+ push: ${{ startsWith(github.ref, 'refs/tags') }}
cache-from: type=gha
cache-to: type=gha,mode=max
- tags: nginx/nginx-kubernetes-gateway:${{ needs.vars.outputs.sha }}
build-args: |
VERSION=${{ needs.vars.outputs.version }}
GIT_COMMIT=${{ needs.vars.outputs.sha }}
@@ -137,7 +159,7 @@ jobs:
uses: aquasecurity/trivy-action@0.2.3
continue-on-error: true
with:
- image-ref: nginx/nginx-kubernetes-gateway:${{ needs.vars.outputs.sha }}
+ image-ref: ghcr.io/nginxinc/nginx-kubernetes-gateway:${{ steps.meta.outputs.version }}
format: 'template'
template: '@/contrib/sarif.tpl'
output: 'trivy-results-nginx-kubernetes-gateway.sarif'
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
new file mode 100644
index 0000000000..4921286bac
--- /dev/null
+++ b/.github/workflows/release.yaml
@@ -0,0 +1,125 @@
+name: Create Draft Release
+
+on:
+ push:
+ branches:
+ - release-*
+ workflow_dispatch:
+ inputs:
+ tagFrom:
+ description: The tag to create the release from.
+ required: true
+ type: string
+ tagTo:
+ description: The tag to create the release to.
+ required: true
+ type: string
+ branch:
+ description: The branch where the release will be created.
+ required: true
+ type: string
+
+jobs:
+
+ binary:
+ name: Create Draft Release
+ runs-on: ubuntu-20.04
+ steps:
+ - uses: actions/setup-node@v3
+ - run: npm install semver
+ - uses: actions/github-script@v6
+ continue-on-error: true
+ with:
+ script: |
+ const semver = require('semver');
+ const ref = context.ref.split("/")[2]
+
+ const releases = (await github.rest.repos.listReleases({
+ owner: context.payload.repository.owner.login,
+ repo: context.payload.repository.name,
+ per_page: 100,
+ })).data
+
+ let latest_release
+ const latest_release_current_branch = releases.find(release => !release.draft && release.tag_name.startsWith("v" + ref.split("-")[1]))
+
+ if (latest_release_current_branch === undefined){
+ latest_release = (await github.rest.repos.getLatestRelease({
+ owner: context.payload.repository.owner.login,
+ repo: context.payload.repository.name,
+ })).data.tag_name
+ } else {
+ latest_release = latest_release_current_branch.tag_name
+ }
+
+ let tagFrom, tagTo, branch
+ if (context.eventName === 'workflow_dispatch'){
+ console.log(`Dispatch run with inputs: ${JSON.stringify(context.payload.inputs)}`)
+ ;({ tagFrom, tagTo, branch } = context.payload.inputs)
+ } else {
+ ;({ tagFrom, tagTo, branch } = {
+ tagFrom: latest_release,
+ tagTo: 'next',
+ branch: ref,
+ })
+ console.log(`Push run with: { tagFrom: ${tagFrom}, tagTo: ${tagTo}, branch: ${branch} }`)
+ }
+ console.log(`The latest release was ${tagFrom}`)
+
+ let version = tagTo.replace('v', '')
+ if (version === 'next'){
+ const temp_notes = (await github.rest.repos.generateReleaseNotes({
+ owner: context.payload.repository.owner.login,
+ repo: context.payload.repository.name,
+ tag_name: tagTo,
+ previous_tag_name: tagFrom,
+ target_commitish: branch,
+ })).data.body
+
+ let level
+ temp_notes.includes("### ๐ Features") ? level = 'minor' : level = 'patch'
+ temp_notes.includes("### ๐ฃ Breaking Changes") ? level = 'major' : level = level
+ version = semver.inc(tagFrom, level)
+ console.log(`The level of the release is ${level}`)
+ }
+ const draft = releases.find((r) => r.draft && r.tag_name === "v"+version)
+ const draft_found = !(draft === undefined)
+
+ console.log(`The next version is v${version}`)
+
+ const release_notes = (await github.rest.repos.generateReleaseNotes({
+ owner: context.payload.repository.owner.login,
+ repo: context.payload.repository.name,
+ tag_name: 'v' + version,
+ previous_tag_name: tagFrom,
+ target_commitish: branch,
+ }))
+
+ let release
+ if (draft_found){
+ console.log("Draft found")
+ release = (await github.rest.repos.updateRelease({
+ owner: context.payload.repository.owner.login,
+ repo: context.payload.repository.name,
+ release_id: draft.id,
+ tag_name: 'v' + version,
+ target_commitish: branch,
+ name: 'v' + version,
+ body: release_notes.data.body,
+ draft: true,
+ }))
+ } else {
+ console.log("Draft not found")
+ release = (await github.rest.repos.createRelease({
+ owner: context.payload.repository.owner.login,
+ repo: context.payload.repository.name,
+ tag_name: 'v' + version,
+ target_commitish: ref,
+ name: 'v' + version,
+ body: release_notes.data.body,
+ draft: true,
+ }))
+ }
+
+ console.log(`Release created: ${release.data.html_url}`)
+ console.log(`Release notes: ${release_notes.data.body}`)