Last active
June 17, 2025 10:07
-
-
Save airtonix/3e7d7207736881506acb1acd3ec03cf0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# read the JSON input from stdin | |
inputs=$(cat); | |
# pick the paths_released from the JSON input and turn it into a bash array | |
paths_array=$(jq -r '.paths_released | fromjson | .[]' <<< "$inputs") | |
for release in $paths_array; do | |
echo "Creating release branch for $release" | |
data=$( | |
echo "$inputs" | | |
jq -r \ | |
--arg release "$release" \ | |
'to_entries | |
| map( | |
select( .key | startswith($release) ) | |
| .key |= sub($release + "--"; "") | |
) | |
| from_entries' | |
) | |
tag_name=$(echo "$data" | jq -r '.tag_name') | |
branch_name="release/$tag_name" | |
echo "$branch_name" | |
git branch "$branch_name" "$tag_name" | |
git push origin "$branch_name" | |
done |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
manifest_path="$1" | |
if [[ -z "$manifest_path" ]]; then | |
echo "Usage: $0 <manifest.json>" | |
exit 1 | |
fi | |
# turn { "key": "value" } into ["key@vvalue"] | |
function parse_manifest_versions() { | |
jq -r ' | |
to_entries | |
| .[] | |
| .key |= split("/") | |
| .key |= .[-1] | |
| "\(.key)@v\(.value)" | |
' <<<"$(cat)" | |
} | |
function newlines_to_array() { | |
jq -R -s -c 'split("\n") | map(select(length > 0))' | |
} | |
# list remote release branches that are open PRs with the label "autorelease: pending" | |
# return a JSON array of objects with the PR number, branch name, and labels | |
function get_remote_release_pr_branches() { | |
gh pr list --state open --json headRefName,labels | | |
jq -rc ' | |
map(select( .labels | any(.name == "autorelease: pending") )) | | |
map({ | |
headRefName: .headRefName, | |
remoteRefName: ("refs/remotes/origin/" + .headRefName), | |
}) | |
' | |
} | |
# list remote release branches | |
# return branches names with only the last part of the refname | |
# e.g. refs/remotes/origin/release-foo -> release-foo | |
function get_remote_release_snapshot_branches() { | |
git for-each-ref \ | |
--format='%(refname:lstrip=-2)' \ | |
'refs/remotes/origin/release/*' | | |
jq -R -s -c ' | |
split("\n") | | |
map( select(length > 0) ) | | |
map({ | |
headRefName: ., | |
remoteRefName: ("refs/remotes/origin/" + .) | |
}) | |
' | |
} | |
new_versions=$(cat "$manifest_path" | parse_manifest_versions | newlines_to_array) | |
conflicts=$( | |
jq -n \ | |
--argjson new_versions "$new_versions" \ | |
'{"new_versions": $new_versions, "conflicts": []}' | |
) | |
while read -r branch_data; do | |
if [[ -z "$branch_data" ]]; then | |
continue | |
fi | |
branch_name=$(echo "$branch_data" | jq -r '.headRefName') | |
remoteRefName=$(echo "$branch_data" | jq -r '.remoteRefName') | |
branch_versions=$(git show "$remoteRefName:$manifest_path" | parse_manifest_versions) | |
# # use jq to perform an intersection of the versions | |
intersection=$( | |
jq -n \ | |
--argjson new_versions "$(echo "$new_versions" | jq -R -s -c 'split(" ")')" \ | |
--argjson branch_versions "$(echo "$branch_versions" | jq -R -s -c 'split(" ")')" \ | |
'$new_versions | map(select(. as $v | $branch_versions | index($v)))' | |
) | |
# count the number of versions in the intersection | |
intersection_count=$(jq length <<<"$intersection") | |
if [[ "$intersection_count" -eq 0 ]]; then | |
continue | |
fi | |
# create a JSON object with the branch name and intersection | |
new_conflicts=$( | |
jq -n \ | |
--arg branch_name "$branch_name" \ | |
--argjson count "$intersection_count" \ | |
--argjson intersection "$intersection" \ | |
'{ | |
branch_name: $branch_name, | |
conflicts: $intersection, | |
kind: "proposed", | |
}' | |
) | |
# add the conflicting object to the conflicts array | |
conflicts=$(jq --argjson new_conflicts "$new_conflicts" '.conflicts += [$new_conflicts]' <<<"$conflicts") | |
done <<<"$(jq -c '.[]' <<<"$(get_remote_release_pr_branches)")" | |
while read -r branch_data; do | |
if [[ -z "$branch_data" ]]; then | |
continue | |
fi | |
branch_ref=$(echo "$branch_data" | jq -r '.remoteRefName') | |
branch_name=$(echo "$branch_data" | jq -r '.headRefName') | |
branch_versions=$(git show "$branch_ref:$manifest_path" | parse_manifest_versions | newlines_to_array) | |
# use jq to perform an intersection of the versions | |
intersection=$( | |
jq -n \ | |
--argjson new_versions "${new_versions}" \ | |
--argjson branch_versions "${branch_versions}" \ | |
'$new_versions | map(select(. as $v | $branch_versions | index($v)))' | |
) | |
# count the number of versions in the intersection | |
intersection_count=$(jq length <<<"$intersection") | |
if [[ "$intersection_count" -eq 0 ]]; then | |
continue | |
fi | |
# create a JSON object with the branch name and intersection | |
new_conflicts=$( | |
jq -n \ | |
--arg branch_name "$branch_name" \ | |
--argjson count "$intersection_count" \ | |
--argjson intersection "$intersection" \ | |
'{ | |
branch_name: $branch_name, | |
conflicts: $intersection, | |
kind: "released", | |
}' | |
) | |
# add the conflicting object to the conflicts array | |
conflicts=$(jq --argjson new_conflicts "$new_conflicts" '.conflicts += [$new_conflicts]' <<<"$conflicts") | |
done <<<"$(jq -c '.[]' <<<"$(get_remote_release_snapshot_branches)")" | |
echo "$conflicts" | jq -c |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/refs/heads/main/schemas/config.json", | |
"versioning": "always-bump-patch", | |
"include-component-in-tag": true, | |
"include-v-in-tag": true, | |
"tag-separator": "@", | |
"separate-pull-requests": true, | |
"bump-minor-pre-major": true, | |
"bump-patch-for-minor-pre-major": true, | |
"release-type": "node", | |
"packages": { | |
"apps/one": {}, | |
"apps/two": {}, | |
"pkgs/ui": {} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/refs/heads/main/schemas/config.json", | |
"versioning": "always-bump-minor", | |
"include-component-in-tag": true, | |
"include-v-in-tag": true, | |
"tag-separator": "@", | |
"separate-pull-requests": true, | |
"bump-minor-pre-major": true, | |
"bump-patch-for-minor-pre-major": true, | |
"always-update": true, | |
"always-link-local": true, | |
"initial-version": "0.0.1", | |
"release-type": "node", | |
"packages": { | |
"apps/one": {}, | |
"apps/two": {}, | |
"pkgs/ui": {} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Pr | |
on: | |
pull_request: | |
branches: | |
- main | |
- release/* | |
concurrency: | |
group: ${{ github.workflow }}-${{ github.ref }} | |
permissions: | |
actions: read | |
contents: write | |
issues: write | |
deployments: write | |
pull-requests: write | |
id-token: write | |
jobs: | |
ReleaseConflictCheck: | |
runs-on: ubuntu-latest | |
# is this a release please PR? test the labels | |
# release please creates labels for release prs like `pending-autorelease` | |
# if this isn't a release please PR, we don't need to do anything | |
if: contains(github.event.pull_request.labels.*.name, 'pending-autorelease') | |
steps: | |
# release please updates the release-please-manifest.json file with it's proposed versions | |
# find that and check if the version is already in use | |
# the file lookws like : | |
# { | |
# "apps/one": "0.1.0", | |
# "apps/two": "0.1.0", | |
# } | |
# | |
# the tags we're looking for look like this: | |
# - [email protected] | |
# - [email protected] | |
# | |
# so we can use the jq command to extract the values and then check if the tag exists | |
# format the output of jq to be the tag we're looking for | |
- name: Check for release conflicts | |
run: | | |
- name: Check conflicts with existing releases | |
shell: bash | |
run: | | |
script=".github/scripts/find-release-tag-conflict.sh" | |
conflicts="$($script .github/release-please-manifest.json)" | |
conflicts_count=$(echo "$conflicts" | jq -s '.conflicts[] | length') | |
released_conflicts="$(echo "$conflicts" | jq -c '.conflicts[] | select(.kind == "released")')" | |
released_conflicts_count=$(echo "$released_conflicts" | jq -s 'length') | |
proposed_conflicts="$(echo "$conflicts" | jq -c '.conflicts[] | select(.kind == "proposed")')" | |
proposed_conflicts_count=$(echo "$proposed_conflicts" | jq -s 'length') | |
echo "conflicts=${conflicts}" >> $GITHUB_OUTPUT | |
echo "conflicts_count=${conflicts_count}" >> $GITHUB_OUTPUT | |
echo "released_conflicts=${released_conflicts}" >> $GITHUB_OUTPUT | |
echo "released_conflicts_count=${released_conflicts_count}" >> $GITHUB_OUTPUT | |
echo "proposed_conflicts=${proposed_conflicts}" >> $GITHUB_OUTPUT | |
echo "proposed_conflicts_count=${proposed_conflicts_count}" >> $GITHUB_OUTPUT | |
if [ "$conflicts_count" -gt 0 ]; then | |
echo "Release conflicts found" | |
echo "$conflicts" | jq -r | |
exit 1 | |
fi | |
echo "No release conflicts found, proceeding with PR" | |
YourOtherPrCheckJob: | |
runs-on: ubuntu-latest | |
steps: | |
- run: | | |
echo true | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Release | |
on: | |
push: | |
branches: | |
# for prod releases | |
- main | |
# for hotfixes | |
- release/* | |
concurrency: | |
group: ${{ github.workflow }}-${{ github.ref }} | |
permissions: | |
actions: read | |
contents: write | |
issues: write | |
deployments: write | |
pull-requests: write | |
id-token: write | |
jobs: | |
Process: | |
runs-on: ubuntu-latest | |
env: | |
RELEASE_BOT_NAME: "Release Bot" | |
RELEASE_BOT_EMAIL: "[email protected]" | |
outputs: | |
releases_created: ${{ steps.release-please.outputs.releases_created }} | |
prs_created: ${{ steps.release-please.outputs.prs_created }} | |
prs: ${{ steps.release-please.outputs.prs }} | |
pr: ${{ steps.release-please.outputs.pr }} | |
sha: ${{ steps.release-please.outputs.sha }} | |
steps: | |
- id: config_filename | |
env: | |
DEFAULT_RELEASE_CONFIG_FILE: release-please-config.json | |
HOTFIX_RELEASE_CONFIG_FILE: release-please-config.hotfix.json | |
run: | | |
case "${{ github.ref_name }}" in | |
release/*) | |
echo "config_filename=${HOTFIX_RELEASE_CONFIG_FILE}" >> $GITHUB_OUTPUT | |
;; | |
*) | |
echo "config_filename=${DEFAULT_RELEASE_CONFIG_FILE}" >> $GITHUB_OUTPUT | |
;; | |
esac | |
- uses: googleapis/release-please-action@v4 | |
id: release-please | |
with: | |
token: "${{ secrets.RELEASE_PLEASE_TOKEN }}" | |
config-file: ".github/${{ steps.config_filename.outputs.config_filename }}" | |
manifest-file: ".github/release-please-manifest.json" | |
target-branch: "${{ github.ref_name }}" | |
- name: Print Release Data | |
run: | | |
echo 'Release Data:' | |
echo ''' | |
${{ toJSON(steps.release-please.outputs) }} | |
''' | |
- name: Checkout Code | |
if: ${{ steps.release-please.outputs.releases_created != 'false' }} | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 10 | |
fetch-tags: true | |
ref: ${{ github.ref_name }} | |
persist-credentials: true | |
- name: Create Release Snapshot Branches | |
if: ${{ steps.release-please.outputs.releases_created != 'false' }} | |
run: | | |
git config --global user.name "$RELEASE_BOT_NAME" | |
git config --global user.email "$RELEASE_BOT_EMAIL" | |
echo "$(jq -cr <<< '${{ toJSON(steps.release-please.outputs) }}')" | | |
.github/scripts/create-release-branch.sh |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment