Skip to content

Commit

Permalink
refactor changesets release preview workflow (#13094)
Browse files Browse the repository at this point in the history
* add format_changelog script

* refactor changesets release preview workflow

* update branch to test and add changeset file

* fix

* add git-token

* add set_pr_body and refactor workflow

* fix multi-line string output

* fix

* fix format

* remove testing branch trigger

* refactor

* add explicit fail exit

* refactor

* add back set -euo pipefail
  • Loading branch information
momentmaker authored May 7, 2024
1 parent 153cce2 commit a0d1ce5
Show file tree
Hide file tree
Showing 4 changed files with 235 additions and 74 deletions.
5 changes: 5 additions & 0 deletions .changeset/many-comics-begin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"chainlink": patch
---

Refactor changesets release preview workflow #internal
67 changes: 67 additions & 0 deletions .github/workflows/changesets-preview-pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#
# This action creates or updates a Release Preview PR that shows which changes are going to be part of the next release.
#

name: Release Preview - Changeset

on:
push:
branches:
- develop

jobs:
changesets-release-preview:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout repository
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2

- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: change
with:
token: ${{ secrets.GITHUB_TOKEN }}
filters: |
core-changeset:
- '.changeset/**'
- name: Setup pnpm
uses: pnpm/action-setup@a3252b78c470c02df07e9d59298aecedc3ccdd6d # v3.0.0
if: steps.change.outputs.core-changeset == 'true'
with:
version: ^8.0.0

- name: Setup node
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
if: steps.change.outputs.core-changeset == 'true'
with:
node-version: 20
cache: pnpm
cache-dependency-path: ./pnpm-lock.yaml

- name: Generate new changelog
if: steps.change.outputs.core-changeset == 'true'
id: changelog
run: pnpm install && ./tools/ci/format_changelog
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Create release preview PR
if: steps.change.outputs.core-changeset == 'true'
uses: peter-evans/create-pull-request@6d6857d36972b65feb161a90e484f2984215f83e # v6.0.5
with:
git-token: ${{ secrets.GITHUB_TOKEN }}
add-paths: |
.changeset/**
CHANGELOG.md
commit-message: "changeset: release preview"
committer: app-token-issuer-releng[bot] <app-token-issuer-releng[bot]@users.noreply.github.com>
branch: changesets/release-preview
title: "[DO NOT MERGE] Changeset Release Preview - v${{ steps.changelog.outputs.version }}"
body: ${{ steps.changelog.outputs.pr_body }}
draft: true
labels: |
release-preview
do-not-merge
74 changes: 0 additions & 74 deletions .github/workflows/cicd-changesets.yml

This file was deleted.

163 changes: 163 additions & 0 deletions tools/ci/format_changelog
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
#!/usr/bin/env bash

set -euo pipefail

if [[ -z "${GITHUB_OUTPUT:-}" ]]; then
echo "GITHUB_OUTPUT environment variable is not set."
exit 1
fi

create_changesets_json() {
echo "[[]]" > changesets.json
}

create_tags_json() {
json="{}"
for tag in "${tags_list[@]}"; do
tag=${tag:1}
json=$(jq --arg k "$tag" '.[$k] = []' <<< "$json")
done
echo "$json" > tags.json
}

append_changeset_content() {
if [[ $1 != "" ]]; then
jq --argjson idx "$changesets_index" --arg str "$1" \
'.[$idx] += [$str]' changesets.json > tmp.json && mv tmp.json changesets.json
fi
}

append_changelog_content() {
for tag in "${tags_list[@]}"; do
tag=${tag:1}
array_length=$(jq -r --arg key "$tag" '.[$key] | length' tags.json)
if [[ $array_length -eq 0 ]]; then
continue
fi
changesets=$(jq -r --arg key "$tag" '.[$key] | join("\n\n")' tags.json)
read -d '' changelog_content <<EOF
${changelog_content}
## ${tag}
${changesets}
EOF
done
}

set_pr_body() {
# GitHub Issues/PRs messages have a max size limit on the message body payload.
# This is the error: `body is too long (maximum is 65536 characters)`.
max_pr_desc_char_length=65000
read -d '' pr_header <<EOF
This PR is a preview of the changes that will be included in the next release. Please do not merge this PR.
---
EOF
if [[ ${#changelog_content} -gt $max_pr_desc_char_length ]]; then
read -d '' pr_body <<EOF
${pr_header}
The changelog content is too long for the PR description. Please view the full changelog in the [CHANGELOG.md](https://github.com/smartcontractkit/chainlink/blob/changesets/release-preview/CHANGELOG.md)
EOF
else
read -d '' pr_body <<EOF
${pr_header}
${changelog_content}
EOF
fi
# for multi-line output
echo "pr_body<<EOF" >> $GITHUB_OUTPUT
echo "${pr_body}" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
}

set_new_changelog_content() {
read -d '' new_changelog <<EOF
${changelog_content}
${current_changelog}
EOF

echo "$new_changelog" > CHANGELOG.md
}

# checks for tags in each changeset entry and append to tags.json
match_tags() {
changesets_with_index=$(jq -r 'to_entries | .[] | "\(.key) \(.value | join(" "))"' changesets.json)

echo "$changesets_with_index" | while IFS= read -r line; do
index="${line%% *}"
changeset_content="${line#* }"
changeset_formatted=$(jq -r --argjson idx "$index" '.[$idx] | join("\n")' changesets.json)
found_tag=""
for tag in "${tags_list[@]}"; do
if [[ "$changeset_content" =~ $tag ]]; then
found_tag=${tag:1}
jq --arg key "$found_tag" --arg val "$changeset_formatted" \
'.[$key] += [$val]' tags.json > tmp.json && mv tmp.json tags.json
fi
done
if [[ $found_tag == "" ]] && [[ ! -z $changeset_content ]]; then
found_tag="untagged"
jq --arg key "$found_tag" --arg val "$changeset_formatted" \
'.[$key] += [$val]' tags.json > tmp.json && mv tmp.json tags.json
fi
done
}

cleanup() {
rm -f CHANGELOG.md.tmp
rm -f changesets.json
rm -f tags.json
}

### SCRIPT STARTS HERE ###

tail -n +2 CHANGELOG.md > CHANGELOG.md.tmp

pnpm changeset version

version=$(jq -r '.version' package.json)
echo "version=$version" >> $GITHUB_OUTPUT

read -d '' changelog_content <<EOF
# Changelog Chainlink Core
## ${version} - PREVIEW
EOF

current_changelog=$(cat CHANGELOG.md.tmp)
is_current_version=false
changesets_index=0
tags_list=( "#nops" "#added" "#changed" "#removed" "#updated" "#deprecation_notice" "#breaking_change" "#db_update" "#wip" "#bugfix" "#internal" "#untagged")

create_changesets_json
create_tags_json

while IFS= read -r line; do
# break when hits the next version
if [[ $line == "## "* ]] && [[ $is_current_version = true ]]; then
break
fi

# look for the latest version
if [[ $line == "## "* ]]; then
is_current_version=true
fi

if [[ $is_current_version = true ]]; then
# saving each changeset to changeset.json
# check for start of changeset entry as it could be multi-lined entry
if [[ $line == "- ["* ]]; then
changesets_index=$((changesets_index+1))
append_changeset_content "$line"
elif [[ $line != "##"* ]]; then
append_changeset_content "$line"
fi
fi
done < CHANGELOG.md

match_tags
append_changelog_content
set_pr_body
set_new_changelog_content
cleanup

0 comments on commit a0d1ce5

Please sign in to comment.