Create forty-poets-dance.md #528
This file contains 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: Create or update release PR | |
on: | |
pull_request: | |
types: [edited] | |
branches: | |
- main | |
push: | |
branches: | |
- develop | |
jobs: | |
create-release-pr: | |
name: Create or update release PR | |
runs-on: ubuntu-latest | |
steps: | |
- name: Save branch name output | |
shell: bash | |
run: echo "branchName=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT | |
id: current-branch-name | |
- name: Create release PR or get existing PR ID | |
id: get-pr | |
uses: actions/github-script@v5 | |
with: | |
github-token: ${{secrets.GITHUB_TOKEN}} | |
script: | | |
/* We already have the id if this is a PR edit event: */ | |
const editedIdMatch = context.ref.match(/^refs\/pull\/(\d+)\//); | |
const editedId = editedIdMatch ? editedIdMatch[1] : null; | |
if (editedId) { | |
return editedId; | |
} | |
const owner = context.repo.owner; | |
const repo = context.repo.repo; | |
const triggeringRefHead = context.ref.split('/').pop(); | |
const base = "main"; | |
const { data: prs } = await github.rest.pulls.list({ | |
owner, | |
repo, | |
}); | |
let pr = prs.find((pr) => { | |
return pr.head.ref === triggeringRefHead && pr.base.ref === base; | |
}); | |
if (!pr) { | |
const { data: latestCommit } = await github.rest.repos.getCommit({ | |
owner, | |
repo, | |
ref: triggeringRefHead, | |
}); | |
const result = await github.rest.pulls.create({ | |
owner, | |
repo, | |
head: triggeringRefHead, | |
base, | |
title: latestCommit.commit.message.replace(/\sGitOrigin-RevId.*/, ""), | |
body: "If this change should result in new package versions please add a changeset before merging. You can do so by clicking the link provided by changeset bot below." | |
}); | |
pr = result.data; | |
} | |
return pr.number; | |
- name: "Checkout" | |
uses: "actions/checkout@v3" | |
with: | |
fetch-depth: 0 | |
- name: Create main branch | |
run: "git branch --track main origin/main" | |
- name: Setup node | |
uses: "actions/setup-node@v3" | |
with: | |
node-version-file: ".nvmrc" | |
- name: yarn install with cache | |
uses: ./.github/actions/yarn-nm-install | |
with: | |
cwd: "." | |
# Lock file differences shouldn't matter for these jobs and it's difficult to | |
# sync up with the test-release-sync workflow (which actually needs the lock | |
# to be updated and runs at the same time) | |
install-mode: "install-allow-lock-update" | |
- name: Run changeset | |
id: changeset | |
run: | | |
echo "$(node ./.github/workflows/runChangeset.mjs | grep changeset)" >> $GITHUB_OUTPUT | |
- name: List changed packages | |
run: | | |
echo "${{ steps.changeset.outputs.changeset }}" | |
- name: Get PR comment vars | |
id: pr-comment-vars | |
run: | | |
echo "lastCommit=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT | |
- name: Update or post comment on PR with link to create changeset | |
id: pr-comment | |
uses: actions/github-script@v5 | |
with: | |
github-token: ${{secrets.GITHUB_TOKEN}} | |
script: | | |
const owner = context.repo.owner; | |
const repo = context.repo.repo; | |
const base = "main"; | |
let pr; | |
/* We already have the id if this is a PR edit event: */ | |
const editedIdMatch = context.ref.match(/^refs\/pull\/(\d+)\//); | |
const editedId = editedIdMatch ? editedIdMatch[1] : null; | |
if (editedId) { | |
const prRequest = await github.rest.pulls.get({ | |
owner, | |
repo, | |
pull_number: editedId, | |
}); | |
pr = prRequest.data; | |
} else { | |
const triggeringRefHead = context.ref.split('/').pop(); | |
const { data: prs } = await github.rest.pulls.list({ | |
owner, | |
repo, | |
}); | |
pr = prs.find((pr) => { | |
return pr.head.ref === triggeringRefHead && pr.base.ref === base; | |
}); | |
if (!pr) { | |
const { data: latestCommit } = await github.rest.repos.getCommit({ | |
owner, | |
repo, | |
ref: triggeringRefHead, | |
}); | |
const result = await github.rest.pulls.create({ | |
owner, | |
repo, | |
head: triggeringRefHead, | |
base, | |
title: latestCommit.commit.message.replace(/\sGitOrigin-RevId.*/, "").substring(0, 30), | |
body: "If this change should result in new package versions please add a changeset before merging. You can do so by clicking the maintainers link provided by changeset-bot below.\n\nPlease note that changeset-bot appears to produce inconsistent / incorrect results with the latest version of changesets when run locally. Be sure to check that it is correctly mentioning the changed packages in the referenced link, or produce the changeset locally `yarn changeset` and push it to the branch." | |
}); | |
pr = result.data; | |
} | |
} | |
const { data: comments } = await github.rest.issues.listComments({ | |
owner, | |
repo, | |
issue_number: pr.number, | |
}); | |
/* 41898282 is github-actions[bot] */ | |
let comment = comments.find(comment => comment.user.id === 41898282); | |
const changesetRawStr = ${{ steps.changeset.outputs.changeset }}.replace(/\n/g, "\\n"); | |
const changeset = JSON.parse(changesetRawStr); | |
const changedPackagesLines = changeset.changedPackages.map(x => `| ${x.name} | ${x.version} |`).join("\n"); | |
const lastCommit = "${{ steps.pr-comment-vars.outputs.lastCommit }}"; | |
const changesetCount = changeset.changesets.length; | |
const changedPackagesStr = changeset.changedPackages.length | |
? `The following public packages have changed files:\n| Changed | Current version |\n| - | - |\n${changedPackagesLines}` | |
: "No public packages have changed files."; | |
const changesetSingle = changesetCount === 1; | |
const commitChangesetLinkBase = `https://github.com/lightsparkdev/js-sdk/new/${pr.head.ref}?filename=.changeset/${changeset.suggestedChangesetId}.md`; | |
const suggestedChangesets = changeset.changedPackages.map(x => `"${x.name}": patch`).join("\n"); | |
const commitChangesetLink = `${commitChangesetLinkBase}&value=${encodeURIComponent(`---\n${suggestedChangesets}\n---\n\n${pr.title}`)}`; | |
const noChangesetStr = `If the changes in this PR should result in new published versions for the packages above please [add a changeset](${commitChangesetLink})`; | |
const hasChangesetStr = `If additional changes have been made that require different versions for any package simply [add another changeset](${commitChangesetLink})`; | |
const changesetStr = `There ${changesetSingle ? "is" : "are"} ${changesetCount || "no"} existing changeset${changesetSingle ? '' : 's'} for this branch. ${changesetCount > 0 ? hasChangesetStr : noChangesetStr}. Any packages that depend on the planned releases will be updated and released automatically in a separate PR.`; | |
const packageReleasesStr = changeset.releases.map(x => `| ${x.name} | ${x.type} |`).join("\n"); | |
const changelogGuidanceStr = `Each changeset corresponds to an update in the CHANGELOG for the packages listed in the changeset. Therefore, you should add a changeset for each noteable package change that this PR contains. For example, if a PR adds two features - one feature for packages A and B and one feature for package C - you should add two changesets. One changeset for packages A and B and one changeset for package C, with a description of each feature. The feature description will end up being the CHANGELOG entry for the packages in the changeset.`; | |
const releasesStr = `${changeset.releases.length ? `The following releases are planned based on the existing changesets:\n\n| Planned releases | Update |\n\| - | - |\n${packageReleasesStr}` : "No releases planned."}`; | |
const commentBody = `${changedPackagesStr}\n\n${changesetStr}\n\n${changelogGuidanceStr}\n\n${releasesStr}\n\nLast updated by commit ${lastCommit}`; | |
if (!comment) { | |
github.rest.issues.createComment({ | |
owner, | |
repo, | |
issue_number: pr.number, | |
body: commentBody, | |
}); | |
} else { | |
github.rest.issues.updateComment({ | |
owner, | |
repo, | |
comment_id: comment.id, | |
body: commentBody, | |
}); | |
} |