Last active
August 31, 2023 13:06
-
-
Save hasparus/2e6c7a70454ee99a5cf9b420109321e3 to your computer and use it in GitHub Desktop.
a bit wasteful CI/CD setup with PR snapshot release and automerged Changesets on main
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
diff --git a/dist/assemble-release-plan.cjs.dev.js b/dist/assemble-release-plan.cjs.dev.js | |
index 3a37c62c975518f975c22e1b4b3974d9b325a5da..cc7b4669526b9ccddcf184f52f8cb5225cc8284e 100644 | |
--- a/dist/assemble-release-plan.cjs.dev.js | |
+++ b/dist/assemble-release-plan.cjs.dev.js | |
@@ -132,16 +132,38 @@ function determineDependents({ | |
} of dependencyVersionRanges) { | |
if (nextRelease.type === "none") { | |
continue; | |
- } else if (shouldBumpMajor({ | |
- dependent, | |
+ } else if (shouldBumpsForPeerDeps({ | |
depType, | |
versionRange, | |
- releases, | |
nextRelease, | |
preInfo, | |
onlyUpdatePeerDependentsWhenOutOfRange: config.___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH.onlyUpdatePeerDependentsWhenOutOfRange | |
})) { | |
- type = "major"; | |
+ // TODO: Remove this patch when https://github.com/changesets/changesets/pull/1132/files | |
+ // is merged and released. Configure the new `updatePeerDependencies` option to `follow`. | |
+ if (!releases.has(dependent)) { | |
+ type = nextRelease.type; | |
+ } else { | |
+ switch (releases.get(dependent).type) { | |
+ case "none": | |
+ type = nextRelease.type; | |
+ break; | |
+ | |
+ case "patch": | |
+ if (nextRelease.type !== "patch") { | |
+ type = nextRelease.type; | |
+ } | |
+ | |
+ break; | |
+ | |
+ case "minor": | |
+ if (nextRelease.type === "major") { | |
+ type = nextRelease.type; | |
+ } | |
+ | |
+ break; | |
+ } | |
+ } | |
} else if ((!releases.has(dependent) || releases.get(dependent).type === "none") && (config.___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH.updateInternalDependents === "always" || !semver__default['default'].satisfies(incrementVersion(nextRelease, preInfo), versionRange))) { | |
switch (depType) { | |
case "dependencies": | |
@@ -239,20 +261,17 @@ function getDependencyVersionRanges(dependentPkgJSON, dependencyRelease) { | |
return dependencyVersionRanges; | |
} | |
-function shouldBumpMajor({ | |
- dependent, | |
+function shouldBumpsForPeerDeps({ | |
depType, | |
versionRange, | |
- releases, | |
nextRelease, | |
preInfo, | |
onlyUpdatePeerDependentsWhenOutOfRange | |
}) { | |
// we check if it is a peerDependency because if it is, our dependent bump type might need to be major. | |
- return depType === "peerDependencies" && nextRelease.type !== "none" && nextRelease.type !== "patch" && ( // 1. If onlyUpdatePeerDependentsWhenOutOfRange set to true, bump major if the version is leaving the range. | |
+ return depType === "peerDependencies" && nextRelease.type !== "none" && ( // 1. If onlyUpdatePeerDependentsWhenOutOfRange set to true, bump major if the version is leaving the range. | |
// 2. If onlyUpdatePeerDependentsWhenOutOfRange set to false, bump major regardless whether or not the version is leaving the range. | |
- !onlyUpdatePeerDependentsWhenOutOfRange || !semver__default['default'].satisfies(incrementVersion(nextRelease, preInfo), versionRange)) && ( // bump major only if the dependent doesn't already has a major release. | |
- !releases.has(dependent) || releases.has(dependent) && releases.get(dependent).type !== "major"); | |
+ !onlyUpdatePeerDependentsWhenOutOfRange || !semver__default['default'].satisfies(incrementVersion(nextRelease, preInfo), versionRange)); | |
} | |
// This function takes in changesets and returns one release per | |
diff --git a/dist/assemble-release-plan.cjs.prod.js b/dist/assemble-release-plan.cjs.prod.js | |
index 87b4c104bf3fa53ba498ced6f81eda0ed4c86436..c37ce949b9ce75b03027f4c06d4d3a8ed54dee32 100644 | |
--- a/dist/assemble-release-plan.cjs.prod.js | |
+++ b/dist/assemble-release-plan.cjs.prod.js | |
@@ -70,15 +70,24 @@ function determineDependents({releases: releases, packagesByName: packagesByName | |
if (!dependentPackage) throw new Error("Dependency map is incorrect"); | |
if (config.ignore.includes(dependent)) type = "none"; else { | |
const dependencyVersionRanges = getDependencyVersionRanges(dependentPackage.packageJson, nextRelease); | |
- for (const {depType: depType, versionRange: versionRange} of dependencyVersionRanges) if ("none" !== nextRelease.type) if (shouldBumpMajor({ | |
- dependent: dependent, | |
+ for (const {depType: depType, versionRange: versionRange} of dependencyVersionRanges) if ("none" !== nextRelease.type) if (shouldBumpsForPeerDeps({ | |
depType: depType, | |
versionRange: versionRange, | |
- releases: releases, | |
nextRelease: nextRelease, | |
preInfo: preInfo, | |
onlyUpdatePeerDependentsWhenOutOfRange: config.___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH.onlyUpdatePeerDependentsWhenOutOfRange | |
- })) type = "major"; else if (!(releases.has(dependent) && "none" !== releases.get(dependent).type || "always" !== config.___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH.updateInternalDependents && semver__default.default.satisfies(incrementVersion(nextRelease, preInfo), versionRange))) switch (depType) { | |
+ })) if (releases.has(dependent)) switch (releases.get(dependent).type) { | |
+ case "none": | |
+ type = nextRelease.type; | |
+ break; | |
+ | |
+ case "patch": | |
+ "patch" !== nextRelease.type && (type = nextRelease.type); | |
+ break; | |
+ | |
+ case "minor": | |
+ "major" === nextRelease.type && (type = nextRelease.type); | |
+ } else type = nextRelease.type; else if (!(releases.has(dependent) && "none" !== releases.get(dependent).type || "always" !== config.___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH.updateInternalDependents && semver__default.default.satisfies(incrementVersion(nextRelease, preInfo), versionRange))) switch (depType) { | |
case "dependencies": | |
case "optionalDependencies": | |
case "peerDependencies": | |
@@ -129,8 +138,8 @@ function getDependencyVersionRanges(dependentPkgJSON, dependencyRelease) { | |
return dependencyVersionRanges; | |
} | |
-function shouldBumpMajor({dependent: dependent, depType: depType, versionRange: versionRange, releases: releases, nextRelease: nextRelease, preInfo: preInfo, onlyUpdatePeerDependentsWhenOutOfRange: onlyUpdatePeerDependentsWhenOutOfRange}) { | |
- return "peerDependencies" === depType && "none" !== nextRelease.type && "patch" !== nextRelease.type && (!onlyUpdatePeerDependentsWhenOutOfRange || !semver__default.default.satisfies(incrementVersion(nextRelease, preInfo), versionRange)) && (!releases.has(dependent) || releases.has(dependent) && "major" !== releases.get(dependent).type); | |
+function shouldBumpsForPeerDeps({depType: depType, versionRange: versionRange, nextRelease: nextRelease, preInfo: preInfo, onlyUpdatePeerDependentsWhenOutOfRange: onlyUpdatePeerDependentsWhenOutOfRange}) { | |
+ return !("peerDependencies" !== depType || "none" === nextRelease.type || onlyUpdatePeerDependentsWhenOutOfRange && semver__default.default.satisfies(incrementVersion(nextRelease, preInfo), versionRange)); | |
} | |
function flattenReleases(changesets, packagesByName, ignoredPackages) { | |
diff --git a/dist/assemble-release-plan.esm.js b/dist/assemble-release-plan.esm.js | |
index c29c008dd709f07cabcb07feff86012c35a01ce5..188668cabc59d078708ba52d9e55bd0ca3e5fdf4 100644 | |
--- a/dist/assemble-release-plan.esm.js | |
+++ b/dist/assemble-release-plan.esm.js | |
@@ -124,16 +124,38 @@ function determineDependents({ | |
} of dependencyVersionRanges) { | |
if (nextRelease.type === "none") { | |
continue; | |
- } else if (shouldBumpMajor({ | |
- dependent, | |
+ } else if (shouldBumpsForPeerDeps({ | |
depType, | |
versionRange, | |
- releases, | |
nextRelease, | |
preInfo, | |
onlyUpdatePeerDependentsWhenOutOfRange: config.___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH.onlyUpdatePeerDependentsWhenOutOfRange | |
})) { | |
- type = "major"; | |
+ // TODO: Remove this patch when https://github.com/changesets/changesets/pull/1132/files | |
+ // is merged and released. Configure the new `updatePeerDependencies` option to `follow`. | |
+ if (!releases.has(dependent)) { | |
+ type = nextRelease.type; | |
+ } else { | |
+ switch (releases.get(dependent).type) { | |
+ case "none": | |
+ type = nextRelease.type; | |
+ break; | |
+ | |
+ case "patch": | |
+ if (nextRelease.type !== "patch") { | |
+ type = nextRelease.type; | |
+ } | |
+ | |
+ break; | |
+ | |
+ case "minor": | |
+ if (nextRelease.type === "major") { | |
+ type = nextRelease.type; | |
+ } | |
+ | |
+ break; | |
+ } | |
+ } | |
} else if ((!releases.has(dependent) || releases.get(dependent).type === "none") && (config.___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH.updateInternalDependents === "always" || !semver.satisfies(incrementVersion(nextRelease, preInfo), versionRange))) { | |
switch (depType) { | |
case "dependencies": | |
@@ -231,20 +253,17 @@ function getDependencyVersionRanges(dependentPkgJSON, dependencyRelease) { | |
return dependencyVersionRanges; | |
} | |
-function shouldBumpMajor({ | |
- dependent, | |
+function shouldBumpsForPeerDeps({ | |
depType, | |
versionRange, | |
- releases, | |
nextRelease, | |
preInfo, | |
onlyUpdatePeerDependentsWhenOutOfRange | |
}) { | |
// we check if it is a peerDependency because if it is, our dependent bump type might need to be major. | |
- return depType === "peerDependencies" && nextRelease.type !== "none" && nextRelease.type !== "patch" && ( // 1. If onlyUpdatePeerDependentsWhenOutOfRange set to true, bump major if the version is leaving the range. | |
+ return depType === "peerDependencies" && nextRelease.type !== "none" && ( // 1. If onlyUpdatePeerDependentsWhenOutOfRange set to true, bump major if the version is leaving the range. | |
// 2. If onlyUpdatePeerDependentsWhenOutOfRange set to false, bump major regardless whether or not the version is leaving the range. | |
- !onlyUpdatePeerDependentsWhenOutOfRange || !semver.satisfies(incrementVersion(nextRelease, preInfo), versionRange)) && ( // bump major only if the dependent doesn't already has a major release. | |
- !releases.has(dependent) || releases.has(dependent) && releases.get(dependent).type !== "major"); | |
+ !onlyUpdatePeerDependentsWhenOutOfRange || !semver.satisfies(incrementVersion(nextRelease, preInfo), versionRange)); | |
} | |
// This function takes in changesets and returns one release per | |
diff --git a/src/determine-dependents.ts b/src/determine-dependents.ts | |
index 97359614f16562adcb66c68011ad3b78b01a1936..719fbe41fb0f2aa5d493258618009b173e44e893 100644 | |
--- a/src/determine-dependents.ts | |
+++ b/src/determine-dependents.ts | |
@@ -68,11 +68,9 @@ export default function determineDependents({ | |
if (nextRelease.type === "none") { | |
continue; | |
} else if ( | |
- shouldBumpMajor({ | |
- dependent, | |
+ shouldBumpsForPeerDeps({ | |
depType, | |
versionRange, | |
- releases, | |
nextRelease, | |
preInfo, | |
onlyUpdatePeerDependentsWhenOutOfRange: | |
@@ -80,7 +78,27 @@ export default function determineDependents({ | |
.onlyUpdatePeerDependentsWhenOutOfRange, | |
}) | |
) { | |
- type = "major"; | |
+ // TODO: Remove this patch when https://github.com/changesets/changesets/pull/1132/files | |
+ // is merged and released. Configure the new `updatePeerDependencies` option to `follow`. | |
+ if (!releases.has(dependent)) { | |
+ type = nextRelease.type; | |
+ } else { | |
+ switch (releases.get(dependent)!.type) { | |
+ case "none": | |
+ type = nextRelease.type; | |
+ break; | |
+ case "patch": | |
+ if (nextRelease.type !== "patch") { | |
+ type = nextRelease.type; | |
+ } | |
+ break; | |
+ case "minor": | |
+ if (nextRelease.type === "major") { | |
+ type = nextRelease.type; | |
+ } | |
+ break; | |
+ } | |
+ } | |
} else if ( | |
(!releases.has(dependent) || | |
releases.get(dependent)!.type === "none") && | |
@@ -206,19 +224,15 @@ function getDependencyVersionRanges( | |
return dependencyVersionRanges; | |
} | |
-function shouldBumpMajor({ | |
- dependent, | |
+function shouldBumpsForPeerDeps({ | |
depType, | |
versionRange, | |
- releases, | |
nextRelease, | |
preInfo, | |
onlyUpdatePeerDependentsWhenOutOfRange, | |
}: { | |
- dependent: string; | |
depType: DependencyType; | |
versionRange: string; | |
- releases: Map<string, InternalRelease>; | |
nextRelease: InternalRelease; | |
preInfo: PreInfo | undefined; | |
onlyUpdatePeerDependentsWhenOutOfRange: boolean; | |
@@ -227,16 +241,9 @@ function shouldBumpMajor({ | |
return ( | |
depType === "peerDependencies" && | |
nextRelease.type !== "none" && | |
- nextRelease.type !== "patch" && | |
// 1. If onlyUpdatePeerDependentsWhenOutOfRange set to true, bump major if the version is leaving the range. | |
// 2. If onlyUpdatePeerDependentsWhenOutOfRange set to false, bump major regardless whether or not the version is leaving the range. | |
(!onlyUpdatePeerDependentsWhenOutOfRange || | |
- !semver.satisfies( | |
- incrementVersion(nextRelease, preInfo), | |
- versionRange | |
- )) && | |
- // bump major only if the dependent doesn't already has a major release. | |
- (!releases.has(dependent) || | |
- (releases.has(dependent) && releases.get(dependent)!.type !== "major")) | |
+ !semver.satisfies(incrementVersion(nextRelease, preInfo), versionRange)) | |
); | |
} |
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
// @ts-check | |
const { default: changesets } = require('@changesets/cli/commit') | |
module.exports.default = { | |
// We include changesets in usual commits. | |
getAddMessage: null, | |
/** | |
* @param {import('@changesets/types').ReleasePlan} releasePlan | |
* @param {{ | |
* skipCI?: boolean | 'add' | 'version' | |
* }} options | |
*/ | |
async getVersionMessage(releasePlan, options) { | |
let message = await changesets.getVersionMessage(releasePlan, options) | |
const hasMajor = releasePlan.releases.some((release) => release.type === 'major') | |
// This prefix stops the breaking changes from getting automatically released. See ci.yml. | |
if (hasMajor) message = 'MAJOR 🚀 ' + message.trimStart() | |
return message | |
}, | |
} |
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: 'Check & Release' | |
concurrency: | |
group: ${{ github.ref_name }} | |
cancel-in-progress: true | |
on: | |
pull_request: | |
push: | |
branches: | |
- main | |
jobs: | |
ci: | |
name: Check and prerelease | |
if: ${{ github.head_ref != 'changeset-release/main' }} | |
runs-on: ubuntu-latest | |
timeout-minutes: 20 | |
env: | |
NPM_TOKEN: ${{ secrets.GRAPHPROTOCOL_NPM_TOKEN }} | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} | |
TURBO_TEAM: ${{ vars.TURBO_TEAM }} | |
steps: | |
- name: Checkout the repo | |
uses: actions/checkout@v3 | |
with: | |
fetch-depth: 20 | |
- name: Set up pnpm | |
uses: pnpm/action-setup@v2 | |
- name: Install dependencies | |
run: | | |
echo -e "\n//registry.npmjs.org/:_authToken=${{ env.NPM_TOKEN }}" >> .npmrc | |
pnpm install | |
- name: Build | |
run: pnpm build | |
- name: Lint and typecheck | |
run: pnpm check | |
- name: Run tests | |
run: pnpm test | |
- name: Get NPM tag | |
run: | | |
tag="${BRANCH_NAME##*/}" | |
tag="${tag//_/-}" # Replace underscores with hyphens | |
echo "npm tag: $tag" | |
echo "tag=$tag" >> $GITHUB_OUTPUT | |
id: get_tag | |
env: | |
BRANCH_NAME: ${{ github.head_ref || github.ref_name }} | |
- name: Release snapshot | |
if: ${{ github.ref_name != 'main' && !github.event.pull_request.draft }} | |
uses: the-guild-org/[email protected] | |
with: | |
tag: ${{ steps.get_tag.outputs.tag }} | |
- name: Create a release PR or publish to NPM | |
if: ${{ github.ref_name == 'main' }} | |
uses: changesets/action@v1 | |
with: | |
version: pnpm changeset version | |
publish: pnpm changeset:publish | |
env: | |
GITHUB_TOKEN: ${{ secrets.FINEGRAINED_WRITE_GITHUB_PAT }} | |
- name: Report package size change | |
if: ${{ github.ref_name != 'main' && !github.event.pull_request.draft }} | |
uses: hasparus/pkg-size-action@develop | |
with: | |
build-command: pnpm build | |
display-size: gzip | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
release: | |
name: Automerge non-major release PR | |
if: ${{ github.head_ref == 'changeset-release/main' }} | |
runs-on: ubuntu-latest | |
timeout-minutes: 2 | |
steps: | |
- name: Checkout the repo | |
uses: actions/checkout@v3 | |
with: | |
fetch-depth: 0 | |
- name: Set up pnpm | |
uses: pnpm/action-setup@v2 | |
- name: Install dependencies | |
run: | | |
echo -e "\n//registry.npmjs.org/:_authToken=${{ env.NPM_TOKEN }}" >> .npmrc | |
pnpm install | |
- name: Check if release is semver Major | |
continue-on-error: true | |
run: | | |
git fetch origin main | |
git log origin/main..HEAD | grep -q "MAJOR 🚀" | |
id: is_major | |
- name: Merge patch and minor release PRs | |
if: steps.is_major.outcome == 'failure' | |
uses: juliangruber/merge-pull-request-action@v1 | |
with: | |
github-token: ${{ secrets.FINEGRAINED_WRITE_GITHUB_PAT }} | |
number: ${{ github.event.pull_request.number }} | |
repo: ${{ github.repository }} | |
method: squash |
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
{ | |
"$schema": "https://unpkg.com/@changesets/[email protected]/schema.json", | |
"changelog": "@changesets/cli/changelog", | |
"commit": ["../.github/scripts/changeset-commit.cjs", { "skipCI": false }], | |
"fixed": [], | |
"linked": [], | |
"access": "public", | |
"baseBranch": "origin/main", | |
"updateInternalDependencies": "patch", | |
"ignore": [], | |
"snapshot": { | |
"useCalculatedVersion": true, | |
"prereleaseTemplate": "{tag}-{timestamp}-{commit}" | |
}, | |
"___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": { | |
"onlyUpdatePeerDependentsWhenOutOfRange": true | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment