Skip to content

Instantly share code, notes, and snippets.

@hasparus
Last active August 31, 2023 13:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hasparus/2e6c7a70454ee99a5cf9b420109321e3 to your computer and use it in GitHub Desktop.
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
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))
);
}
// @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
},
}
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/changesets-snapshot-action@v0.0.1
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
{
"$schema": "https://unpkg.com/@changesets/config@2.3.0/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