diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 6f6043ec31..c3ba8214e2 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -1,44 +1,118 @@ -name: release +# This code is borrowed from https://github.com/kubernetes-sigs/cluster-api/blob/main/.github/workflows/release.yaml +name: Create Release on: push: - # Sequence of patterns matched against refs/tags - tags: - - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10 + branches: + - main + paths: + - 'releasenotes/*.md' -permissions: - contents: write # Allow to create a release. +permissions: {} jobs: - build: + push_release_tags: + permissions: + contents: write # Allow to push tags + runs-on: ubuntu-latest + outputs: + release_tag: ${{ steps.release-version.outputs.release_version }} + if: github.repository == 'kubernetes-sigs/cluster-api-provider-openstack' + steps: + - name: Checkout code + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # tag=v5.0.0 + with: + fetch-depth: 0 + - name: Get changed files + id: changed-files + uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c # v46.0.5 + - name: Get release version + id: release-version + run: | + if [[ ${{ steps.changed-files.outputs.all_changed_files_count }} != 1 ]]; then + echo "1 release notes file should be changed to create a release tag, found ${{ steps.changed-files.outputs.all_changed_files_count }}" + exit 1 + fi + for changed_file in ${{ steps.changed-files.outputs.all_changed_files }}; do + export RELEASE_VERSION=$(echo "${changed_file}" | grep -oP '(?<=/)[^/]+(?=\.md)') + echo "RELEASE_VERSION=${RELEASE_VERSION}" >> ${GITHUB_ENV} + echo "RELEASE_VERSION=${RELEASE_VERSION}" >> ${GITHUB_OUTPUT} + if [[ "${RELEASE_VERSION}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$ ]]; then + echo "Valid semver: ${RELEASE_VERSION}" + else + echo "Invalid semver: ${RELEASE_VERSION}" + exit 1 + fi + done + - name: Determine the release branch to use + run: | + if [[ ${RELEASE_VERSION} =~ beta ]] || [[ ${RELEASE_VERSION} =~ alpha ]]; then + export RELEASE_BRANCH=main + echo "RELEASE_BRANCH=${RELEASE_BRANCH}" >> ${GITHUB_ENV} + echo "This is a beta or alpha release, will use release branch ${RELEASE_BRANCH}" + else + export RELEASE_BRANCH=release-$(echo ${RELEASE_VERSION} | sed -E 's/^v([0-9]+)\.([0-9]+)\..*$/\1.\2/') + echo "RELEASE_BRANCH=${RELEASE_BRANCH}" >> ${GITHUB_ENV} + echo "This is not a beta or alpha release, will use release branch ${RELEASE_BRANCH}" + fi + - name: Create or checkout release branch + run: | + if git show-ref --verify --quiet "refs/remotes/origin/${RELEASE_BRANCH}"; then + echo "Branch ${RELEASE_BRANCH} already exists" + git checkout "${RELEASE_BRANCH}" + else + git checkout -b "${RELEASE_BRANCH}" + git push origin "${RELEASE_BRANCH}" + echo "Created branch ${RELEASE_BRANCH}" + fi + - name: Validate tag does not already exist + run: | + if [[ -n "$(git tag -l "${RELEASE_VERSION}")" ]]; then + echo "Tag ${RELEASE_VERSION} already exists, exiting" + exit 1 + fi + - name: Create Release Tag + run: | + git config user.name "${GITHUB_ACTOR}" + git config user.email "${GITHUB_ACTOR}@users.noreply.github.com" + git tag -a ${RELEASE_VERSION} -m ${RELEASE_VERSION} + git push origin ${RELEASE_VERSION} + echo "Created tags ${RELEASE_VERSION}" + release: name: create draft release runs-on: ubuntu-latest + needs: push_release_tags + permissions: + contents: write # Allow to create a release. steps: - - name: Set env - run: echo "RELEASE_TAG=${GITHUB_REF:10}" >> $GITHUB_ENV - - name: checkout code - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # tag=v5.0.0 - with: - fetch-depth: 0 - - name: Calculate go version - run: echo "go_version=$(make go-version)" >> $GITHUB_ENV - - name: Set up Go - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # tag=v6.0.0 - with: - go-version: ${{ env.go_version }} - - name: generate release artifacts - run: | - make release - - name: generate release notes - # Ignore failures for release-notes generation so they could still get - # generated manually before publishing. - run: | - make generate-release-notes || echo "Failed to generate release notes" >> _releasenotes/${{ env.RELEASE_TAG }}.md - env: - GH_TOKEN: ${{ github.token }} - - name: Release - uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090 # tag=v2.4.1 - with: - draft: true - files: out/* - body_path: _releasenotes/${{ env.RELEASE_TAG }}.md + - name: Set env + run: echo "RELEASE_TAG=${RELEASE_TAG}" >> ${GITHUB_ENV} + env: + RELEASE_TAG: ${{needs.push_release_tags.outputs.release_tag}} + - name: checkout code + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # tag=v5.0.0 + with: + fetch-depth: 0 + ref: ${{ env.RELEASE_TAG }} + - name: Calculate go version + run: echo "go_version=$(make go-version)" >> ${GITHUB_ENV} + - name: Set up Go + uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # tag=v6.0.0 + with: + go-version: ${{ env.go_version }} + - name: generate release artifacts + run: | + make release + env: + GH_TOKEN: ${{ github.token }} + - name: get release notes + run: | + curl -L "https://raw.githubusercontent.com/${{ github.repository }}/main/releasenotes/${{ env.RELEASE_TAG }}.md" \ + -o "${{ env.RELEASE_TAG }}.md" + - name: Release + uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090 # tag=v2.4.1 + with: + draft: true + files: out/* + body_path: ${{ env.RELEASE_TAG }}.md + tag_name: ${{ env.RELEASE_TAG }} diff --git a/Makefile b/Makefile index 6ccff05abf..3358f5d2c9 100644 --- a/Makefile +++ b/Makefile @@ -448,14 +448,13 @@ staging-manifests: ## -------------------------------------- ##@ Release ## -------------------------------------- - ifneq (,$(findstring -,$(RELEASE_TAG))) PRE_RELEASE=true endif PREVIOUS_TAG ?= $(shell git tag -l | grep -E "^v[0-9]+\.[0-9]+\.[0-9]+$$" | sort -V | grep -B1 $(RELEASE_TAG) | head -n 1 2>/dev/null) ## set by Prow, ref name of the base branch, e.g., main RELEASE_DIR := out -RELEASE_NOTES_DIR := _releasenotes +RELEASE_NOTES_DIR := releasenotes .PHONY: $(RELEASE_DIR) $(RELEASE_DIR): @@ -478,7 +477,7 @@ list-image: gcloud container images list-tags $(STAGING_REGISTRY)/$(IMAGE) --filter="tags=('$(RELEASE_TAG)')" --format=json .PHONY: release -release: $(RELEASE_NOTES) clean-release $(RELEASE_DIR) ## Builds and push container images using the latest git tag for the commit. +release: $(RELEASE_NOTES) $(RELEASE_DIR) ## Builds and push container images using the latest git tag for the commit. @if [ -z "${RELEASE_TAG}" ]; then echo "RELEASE_TAG is not set"; exit 1; fi @if ! [ -z "$$(git status --porcelain)" ]; then echo "Your local git repository contains uncommitted changes, use git clean before proceeding."; fi git checkout "${RELEASE_TAG}" @@ -486,6 +485,7 @@ release: $(RELEASE_NOTES) clean-release $(RELEASE_DIR) ## Builds and push conta $(MAKE) manifest-modification REGISTRY=$(PROD_REGISTRY) $(MAKE) release-manifests $(MAKE) release-templates + $(MAKE) generate-release-notes .PHONY: manifest-modification manifest-modification: # Set the manifest images to the staging/production bucket.