diff --git a/.github/workflows/auto-release.yaml b/.github/workflows/auto-release.yaml index e69de29..f2b0ae1 100644 --- a/.github/workflows/auto-release.yaml +++ b/.github/workflows/auto-release.yaml @@ -0,0 +1,236 @@ +name: Automated patch release + +on: + schedule: + - cron: '0 12 1 * *' + workflow_dispatch: + +jobs: + check: + runs-on: ubuntu-latest + outputs: + has_changes: ${{ steps.check-prs.outputs.has_changes }} + non_patch_prs: ${{ steps.check-prs.outputs.non_patch_prs }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # We only continue if the last release was actually a month ago + - name: Check age of last release + id: check-age + env: + GH_TOKEN: ${{ github.token }} + run: | + RELEASE=$(gh release view --json name,createdAt) + CREATED_AT=$(echo "$RELEASE" | jq -r .createdAt) + CREATED_TIMESTAMP=$(date -d "$CREATED_AT" +%s) + CURRENT_TIMESTAMP=$(date +%s) + DAYS_DIFF=$(( ($CURRENT_TIMESTAMP - $CREATED_TIMESTAMP) / 86400 )) + + echo "Latest release $(echo "$RELEASE" | jq .name) was published at $CREATED_AT, $DAYS_DIFF days ago." + echo "skip=$([ $DAYS_DIFF -lt 30 ] && echo "true" || echo "false")" >> "$GITHUB_OUTPUT" + + # Any PR since last month that is not authored by renovate and does NOT have a "patch" label will cause this run to be skipped. + # Renovate automerges minor changes as well, but we consider such as patches as it's only affects packages. + - name: Check for merged PRs since last release + id: check-prs + if: ${{ steps.check-age.outputs.skip != 'true' }} + env: + GH_TOKEN: ${{ github.token }} + run: | + LAST_RELEASE=$(git describe --tags --abbrev=0 2>/dev/null || echo "none") + if [ "$LAST_RELEASE" = "none" ]; then + MERGED_PRS=$(gh pr list --state merged --limit 1 --json number) + else + MERGED_PRS=$(gh pr list --state merged --base ${{ github.event.repository.default_branch }} --search "merged:>=$(git log -1 --format=%aI $LAST_RELEASE | cut -d'T' -f1)" --json author,title,labels,number) + fi + + if [ "$(echo $MERGED_PRS | jq '. | length')" -gt 0 ]; then + FILTERED_PRS=$(echo "$MERGED_PRS" | jq '[.[] | select(.author.login != "app/renovate") | select((.labels | length < 1) or (.labels | all(.name != "patch")))]') + FILTERED_PRS_AMOUNT=$(echo $FILTERED_PRS | jq length) + if [ "$FILTERED_PRS_AMOUNT" -gt 0 ]; then + echo "::warning title=Non-patch PRs found::A total of $FILTERED_PRS_AMOUNT PRs that are possibly not patch releases have been found" + echo $FILTERED_PRS | jq '.[] | {title: .title, author: "\(.author.login) (\(.author.name))", url: "https://github.com/puzzle/cert-manager-webhook-dnsimple/pull/\(.number)", number: .number}' + + echo "has_changes=false" >> "$GITHUB_OUTPUT" + echo "non_patch_prs=true" >> "$GITHUB_OUTPUT" + exit 0 + fi + + echo "Has changes" + echo "has_changes=true" >> "$GITHUB_OUTPUT" + exit 0 + fi + + echo "Has no changes" + echo "has_changes=false" >> "$GITHUB_OUTPUT" + + - name: Notify if bad + id: notify-abort + if: ${{ steps.check-prs.outputs.has_changes == 'false' && steps.check-prs.outputs.non_patch_prs == 'true' }} + env: + GH_TOKEN: ${{ github.token }} + run: | + THIS_RUN=$(gh run --repo ${{ github.repository }} view ${{ github.run_id }} --json jobs --jq '.jobs[] | select(.name == "${{ github.job }}") | .url') + MSG=$(cat <> "$GITHUB_OUTPUT" + echo "app=$APP_VERSION" >> "$GITHUB_OUTPUT" + echo "tag=$TAG" >> "$GITHUB_OUTPUT" + + - name: Update versions + id: update-versions + run: | + export TERM=xterm-color + yq e '.appVersion = "${{ steps.new-versions.outputs.app }}"' -i charts/cert-manager-webhook-dnsimple/Chart.yaml + yq e '.version = "${{ steps.new-versions.outputs.chart }}"' -i charts/cert-manager-webhook-dnsimple/Chart.yaml + yq e '.image.tag = "${{ steps.new-versions.outputs.tag }}"' -i charts/cert-manager-webhook-dnsimple/values.yaml + + git diff + + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + git add -u + + git commit -m "chore: Update versions for chart release ${{ steps.new-versions.outputs.chart }}" + git tag -a "${{ steps.new-versions.outputs.tag }}" -m "Release ${{ steps.new-versions.outputs.tag }}" + + echo "Git tags AFTER creating our own (${{ steps.new-versions.outputs.tag }})" + git tag + + git push && git push origin "${{ steps.new-versions.outputs.tag }}" + + - name: Await docker build + id: docker-build + env: + GH_TOKEN: ${{ github.token }} + run: | + echo "Waiting for release workflow to complete..." + sleep 5 + + # ID can be derived using 'gh workflow list' + # The ID below is of the "Build tagged Docker image" workflow + WORKFLOW_ID=99918806 + RUN_DETAILS=$(gh run list --workflow="$WORKFLOW_ID" --branch="${{ steps.new-versions.outputs.tag }}" --json conclusion,status,url,databaseId) + echo $RUN_DETAILS | jq -r .[0].url + + for i in {1..30}; do + RUN_DETAILS=$(gh run list --workflow="$WORKFLOW_ID" --branch="${{ steps.new-versions.outputs.tag }}" --json conclusion,status,url,databaseId) + if [ $(echo $RUN_DETAILS | jq length) -gt 0 ]; then + RUN_ID=$(echo $RUN_DETAILS | jq -r .[0].databaseId) + STATUS=$(gh run view "$RUN_ID" --json conclusion --jq .conclusion) + if [ "$STATUS" = "success" ]; then + echo "Docker build workflow has concluded" + exit 0 + elif [ "$STATUS" = "failure" ]; then + echo "::error title=Docker build failed::Docker build action has failed" + exit 1 + fi + fi + sleep 20 + done + + echo "::error title=Docker build timed out::Timed out awaiting docker build action" + exit 1 + + trigger-release: + needs: update + uses: ./.github/workflows/helm-release.yaml + with: + release-body-addendum: "Automated release" + + # Only notify on success or failure + notify: + needs: + - update + - check + if: ${{ always() && needs.check.outputs.non_patch_prs != 'true' }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Notify status + env: + GH_TOKEN: ${{ github.token }} + run: | + THIS_RUN=$(gh run --repo ${{ github.repository }} view ${{ github.run_id }} --json jobs --jq '.jobs[] | select(.name == "${{ github.job }}") | .url') + + CONCLUSION=$(gh run view ${{ github.run_id }} --json jobs | jq -r '.jobs[] | select(.name == "update") | .conclusion') + TRIGGER_CONCLUSION=$(gh run view ${{ github.run_id }} --json jobs | jq -r '.jobs[] | select(.name | startswith("trigger-release")) | .conclusion') + echo "Update job conclusion: $CONCLUSION" + echo "Trigger-release job conclusion: $TRIGGER_CONCLUSION" + + if [ "$CONCLUSION" == "success" -a "$TRIGGER_CONCLUSION" == "success" ]; then + MSG=$(cat < Also see: https://github.com/actions/checkout/issues/1467 @@ -40,6 +46,11 @@ jobs: # Workaround to get newlines working echo -e "### Changes since \`${LAST_TAG}\`\n\n${COMMITS}" > msg + + if [[ -n "${{ inputs.release-body-addendum }}" ]]; then + echo -e "\n${{ inputs.release-body-addendum }}" >> msg + fi + gh release edit ${CURRENT_TAG} --notes "$(cat msg)" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/rk_body.json b/.github/workflows/rk_body.json new file mode 100644 index 0000000..96dca86 --- /dev/null +++ b/.github/workflows/rk_body.json @@ -0,0 +1,5 @@ +{ + "avatar": "https://github.githubassets.com/images/icons/emoji/shipit.png", + "username": "cert-manager-webhook-dnsimple", + "text": "This message should be different" +} \ No newline at end of file