Skip to content

Commit

Permalink
Merge pull request #23421 from storybookjs/cherry-pick-deferred-versi…
Browse files Browse the repository at this point in the history
…oning

Release tooling: Defer version bumping to the publish step - Cherry picking #23393
  • Loading branch information
JReinhold authored Jul 12, 2023
2 parents b12ce12 + 5761641 commit b791562
Show file tree
Hide file tree
Showing 8 changed files with 799 additions and 31 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/prepare-patch-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,11 @@ jobs:
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
yarn release:pick-patches
- name: Bump version
- name: Bump version deferred
id: bump-version
if: steps.unreleased-changes.outputs.has-changes-to-release == 'true'
run: |
yarn release:version --release-type patch --verbose
yarn release:version --deferred --release-type patch --verbose
# We need the current version to set the branch name, even when not bumping the version
- name: Get current version
Expand Down Expand Up @@ -121,7 +121,7 @@ jobs:
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
git checkout -b version-patch-from-${{ steps.versions.outputs.current }}
git add .
git commit -m "Bump version from ${{ steps.versions.outputs.current }} to ${{ steps.versions.outputs.next }}" || true
git commit -m "Write changelog for ${{ steps.versions.outputs.next }}" || true
git push --force origin version-patch-from-${{ steps.versions.outputs.current }}
- name: Generate PR description
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/prepare-prerelease.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,10 @@ jobs:
gh run cancel ${{ github.run_id }}
gh run watch ${{ github.run_id }}
- name: Bump version
- name: Bump version deferred
id: bump-version
run: |
yarn release:version --release-type ${{ inputs.release-type || 'prerelease' }} ${{ inputs.pre-id && format('{0} {1}', '--pre-id', inputs.pre-id) || '' }} --verbose
yarn release:version --deferred --release-type ${{ inputs.release-type || 'prerelease' }} ${{ inputs.pre-id && format('{0} {1}', '--pre-id', inputs.pre-id) || '' }} --verbose
- name: Write changelog
env:
Expand All @@ -125,7 +125,7 @@ jobs:
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
git checkout -b version-prerelease-from-${{ steps.bump-version.outputs.current-version }}
git add .
git commit -m "Bump version from ${{ steps.bump-version.outputs.current-version }} to ${{ steps.bump-version.outputs.next-version }}" || true
git commit -m "Write changelog for ${{ steps.bump-version.outputs.next-version }}" || true
git push --force origin version-prerelease-from-${{ steps.bump-version.outputs.current-version }}
- name: Generate PR description
Expand Down
21 changes: 21 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,27 @@ jobs:
run: |
yarn install
- name: Apply deferred version bump and commit
id: version-bump
working-directory: .
run: |
CURRENT_VERSION=$(cat ./code/package.json | jq '.version')
DEFERRED_NEXT_VERSION=$(cat ./code/package.json | jq '.deferredNextVersion')
if [[ "$DEFERRED_NEXT_VERSION" == "null" ]]; then
echo "No deferred version set, not bumping versions"
exit 0
fi
cd scripts
yarn release:version --apply --verbose
cd ..
git config --global user.name "storybook-bot"
git config --global user.email "[email protected]"
git add .
git commit -m "Bump version from $CURRENT_VERSION to $DEFERRED_NEXT_VERSION" || true
git push origin ${{ github.ref_name }}
- name: Get current version
id: version
run: yarn release:get-current-version
Expand Down
558 changes: 558 additions & 0 deletions CONTRIBUTING/RELEASING.md

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions code/__mocks__/fs-extra.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ const readJsonSync = (filePath = '') => JSON.parse(mockFiles[filePath]);
const lstatSync = (filePath) => ({
isFile: () => !!mockFiles[filePath],
});
const writeJson = jest.fn((filePath, json, { spaces } = {}) => {
mockFiles[filePath] = JSON.stringify(json, null, spaces);
});

// eslint-disable-next-line no-underscore-dangle
fs.__setMockFiles = __setMockFiles;
Expand All @@ -29,5 +32,6 @@ fs.readJson = readJson;
fs.readJsonSync = readJsonSync;
fs.existsSync = existsSync;
fs.lstatSync = lstatSync;
fs.writeJson = writeJson;

module.exports = fs;
116 changes: 112 additions & 4 deletions scripts/release/__tests__/version.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,77 @@ describe('Version', () => {
`);
});

it('should throw when apply is combined with releaseType', async () => {
fsExtra.__setMockFiles({
[CODE_PACKAGE_JSON_PATH]: JSON.stringify({ version: '1.0.0' }),
[MANAGER_API_VERSION_PATH]: `export const version = "1.0.0";`,
[VERSIONS_PATH]: `export default { "@storybook/addon-a11y": "1.0.0" };`,
});

await expect(version({ apply: true, releaseType: 'prerelease' })).rejects
.toThrowErrorMatchingInlineSnapshot(`
"[
{
"code": "custom",
"message": "--apply cannot be combined with --exact or --release-type, as it will always read from code/package.json#deferredNextVersion",
"path": []
}
]"
`);
});

it('should throw when apply is combined with exact', async () => {
fsExtra.__setMockFiles({
[CODE_PACKAGE_JSON_PATH]: JSON.stringify({ version: '1.0.0' }),
[MANAGER_API_VERSION_PATH]: `export const version = "1.0.0";`,
[VERSIONS_PATH]: `export default { "@storybook/addon-a11y": "1.0.0" };`,
});

await expect(version({ apply: true, exact: '1.0.0' })).rejects
.toThrowErrorMatchingInlineSnapshot(`
"[
{
"code": "custom",
"message": "--apply cannot be combined with --exact or --release-type, as it will always read from code/package.json#deferredNextVersion",
"path": []
}
]"
`);
});

it('should throw when apply is combined with deferred', async () => {
fsExtra.__setMockFiles({
[CODE_PACKAGE_JSON_PATH]: JSON.stringify({ version: '1.0.0' }),
[MANAGER_API_VERSION_PATH]: `export const version = "1.0.0";`,
[VERSIONS_PATH]: `export default { "@storybook/addon-a11y": "1.0.0" };`,
});

await expect(version({ apply: true, deferred: true })).rejects
.toThrowErrorMatchingInlineSnapshot(`
"[
{
"code": "custom",
"message": "--deferred cannot be combined with --apply",
"path": []
}
]"
`);
});

it('should throw when applying without a "deferredNextVersion" set', async () => {
fsExtra.__setMockFiles({
[CODE_PACKAGE_JSON_PATH]: JSON.stringify({ version: '1.0.0' }),
});

await expect(version({ apply: true })).rejects.toThrowErrorMatchingInlineSnapshot(
`"The 'deferredNextVersion' property in code/package.json is unset. This is necessary to apply a deferred version bump"`
);

expect(fsExtra.writeJson).not.toHaveBeenCalled();
expect(fsExtra.writeFile).not.toHaveBeenCalled();
expect(execaCommand).not.toHaveBeenCalled();
});

it.each([
// prettier-ignore
{ releaseType: 'major', currentVersion: '1.1.1', expectedVersion: '2.0.0' },
Expand Down Expand Up @@ -159,11 +230,21 @@ describe('Version', () => {
{ releaseType: 'patch', currentVersion: '1.1.1-rc.10', expectedVersion: '1.1.1' },
// prettier-ignore
{ exact: '4.2.0-canary.69', currentVersion: '1.1.1-rc.10', expectedVersion: '4.2.0-canary.69' },
// prettier-ignore
{ apply: true, currentVersion: '1.0.0', deferredNextVersion: '1.2.0', expectedVersion: '1.2.0' },
])(
'bump with type: "$releaseType", pre id "$preId" or exact "$exact", from: $currentVersion, to: $expectedVersion',
async ({ releaseType, preId, exact, currentVersion, expectedVersion }) => {
'bump with type: "$releaseType", pre id "$preId" or exact "$exact" or apply $apply, from: $currentVersion, to: $expectedVersion',
async ({
releaseType,
preId,
exact,
apply,
currentVersion,
expectedVersion,
deferredNextVersion,
}) => {
fsExtra.__setMockFiles({
[CODE_PACKAGE_JSON_PATH]: JSON.stringify({ version: currentVersion }),
[CODE_PACKAGE_JSON_PATH]: JSON.stringify({ version: currentVersion, deferredNextVersion }),
[MANAGER_API_VERSION_PATH]: `export const version = "${currentVersion}";`,
[VERSIONS_PATH]: `export default { "@storybook/addon-a11y": "${currentVersion}" };`,
[A11Y_PACKAGE_JSON_PATH]: JSON.stringify({
Expand All @@ -185,7 +266,17 @@ describe('Version', () => {
[VERSIONS_PATH]: `export default { "@storybook/addon-a11y": "${currentVersion}" };`,
});

await version({ releaseType, preId, exact });
await version({ releaseType, preId, exact, apply });
expect(fsExtra.writeJson).toHaveBeenCalledTimes(apply ? 3 : 2);
if (apply) {
// eslint-disable-next-line jest/no-conditional-expect -- guarded against problems with the assertion above
expect(fsExtra.writeJson).toHaveBeenCalledWith(
CODE_PACKAGE_JSON_PATH,
// this call is the write that removes the "deferredNextVersion" property
{ version: currentVersion },
{ spaces: 2 }
);
}

expect(fsExtra.writeJson).toHaveBeenCalledWith(
CODE_PACKAGE_JSON_PATH,
Expand Down Expand Up @@ -231,4 +322,21 @@ describe('Version', () => {
});
}
);

it('should only set version in "deferredNextVersion" when using --deferred', async () => {
fsExtra.__setMockFiles({
[CODE_PACKAGE_JSON_PATH]: JSON.stringify({ version: '1.0.0' }),
});

await version({ releaseType: 'premajor', preId: 'beta', deferred: true });

expect(fsExtra.writeJson).toHaveBeenCalledTimes(1);
expect(fsExtra.writeJson).toHaveBeenCalledWith(
CODE_PACKAGE_JSON_PATH,
{ version: '1.0.0', deferredNextVersion: '2.0.0-beta.0' },
{ spaces: 2 }
);
expect(fsExtra.writeFile).not.toHaveBeenCalled();
expect(execaCommand).not.toHaveBeenCalled();
});
});
Loading

0 comments on commit b791562

Please sign in to comment.