Skip to content

Commit

Permalink
Merge pull request #10516 from marmelab/release-tooling
Browse files Browse the repository at this point in the history
[chore] Improve release tooling
  • Loading branch information
djhi authored Feb 21, 2025
2 parents 1c3f9bb + f8c103e commit f9a814e
Show file tree
Hide file tree
Showing 9 changed files with 918 additions and 1 deletion.
1 change: 1 addition & 0 deletions .env.template
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
GITHUB_ACCESS_TOKEN=your_github_access_token
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ cypress/screenshots
!.yarn/releases
!.yarn/sdks
!.yarn/versions
.env
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -176,3 +176,6 @@ update-sandbox: ## Push the local version of the simple example to the sandbox r

check-documentation-videos-format: ## Check the documentation format
./scripts/check-documentation-videos-format.sh

release: ## Start the release process and publish the packages to npm using lerna
./scripts/release.sh
10 changes: 9 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,14 @@
"run-crm": "cd examples/crm && yarn dev",
"build-crm": "cd examples/crm && yarn build",
"storybook": "storybook dev -p 9010",
"build-storybook": "storybook build -c .storybook -o public --quiet"
"build-storybook": "storybook build -c .storybook -o public --quiet",
"update-changelog": "tsx scripts/update-changelog.ts",
"update-milestones": "tsx scripts/update-milestones.ts",
"create-github-release": "tsx scripts/create-github-release.ts"
},
"devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@octokit/core": "^6.1.4",
"@storybook/addon-actions": "^8.4.4",
"@storybook/addon-controls": "^8.4.4",
"@storybook/addon-storysource": "^8.4.4",
Expand All @@ -37,6 +41,8 @@
"@typescript-eslint/eslint-plugin": "^5.60.0",
"@typescript-eslint/parser": "^5.60.0",
"cross-env": "^5.2.0",
"date-fns": "^3.6.0",
"dotenv": "^16.4.7",
"eslint": "^8.19.0",
"eslint-config-prettier": "^9.1.0",
"eslint-config-react-app": "^7.0.1",
Expand All @@ -53,13 +59,15 @@
"jest-watch-typeahead": "2.2.2",
"lerna": "~7.1.3",
"lint-staged": "^13.0.3",
"lodash": "^4.17.21",
"lolex": "~2.3.2",
"prettier": "~3.2.5",
"raf": "~3.4.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"storybook": "^8.4.4",
"ts-jest": "^29.1.0",
"tsx": "^4.19.2",
"typescript": "^5.1.3",
"whatwg-fetch": "^3.0.0"
},
Expand Down
98 changes: 98 additions & 0 deletions scripts/create-github-release.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import 'dotenv/config';
import { Octokit } from '@octokit/core';
import fs from 'fs';
import path from 'path';
import escapeRegExp from 'lodash/escapeRegExp';

const main = async () => {
if (process.env.RELEASE_DRY_RUN) {
console.log('Dry run mode is enabled');
}

if (!process.env.GITHUB_ACCESS_TOKEN) {
console.error(
'Please provide the GITHUB_ACCESS_TOKEN variable in the .env file'
);
process.exit(1);
}

const version = process.argv[2];

if (!version || !version.match(/^\d{1,2}\.\d{1,2}\.\d{1,2}$/)) {
console.error(`Invalid version provided: ${version}`);
console.error('Usage: yarn run create-github-release <version>');
process.exit(1);
}

const tag_name = `v${version}`;

const octokit = new Octokit({
auth: process.env.GITHUB_ACCESS_TOKEN,
});

console.log(`Fetching latest releases`);
const releases = await octokit.request(
'GET /repos/{owner}/{repo}/releases',
{
owner: 'marmelab',
repo: 'react-admin',
}
);

const alreadyExistingRelease = releases.data.find(
release => release.tag_name === tag_name
);

if (alreadyExistingRelease) {
console.log(`Release ${version} already exists.`);
return;
}

console.log(`Parsing changelog for release ${version}`);

// Read the changelog file
const changelogFilePath = path.join(__dirname, '../CHANGELOG.md');
const changelogContent = fs.readFileSync(changelogFilePath, 'utf-8');

// Create a regular expression to capture the changelog entries for the specified version
const safeVersion = escapeRegExp(version);
const regex = new RegExp(`## ${safeVersion}\n\n([\\s\\S]*?)\n##`, 'g');
const match = regex.exec(changelogContent);

if (!match) {
console.error(
`Could not find changelog entries for version ${version}`
);
process.exit(1);
}

const changelogEntries = match[1].trim();

console.log(`Creating release ${version} from tag ${tag_name}`);

if (process.env.RELEASE_DRY_RUN) {
console.log(
'Would have called GitHub API with',
'POST /repos/{owner}/{repo}/releases',
{
owner: 'marmelab',
repo: 'react-admin',
tag_name,
name: version,
body: changelogEntries,
}
);
} else {
await octokit.request('POST /repos/{owner}/{repo}/releases', {
owner: 'marmelab',
repo: 'react-admin',
tag_name,
name: version,
body: changelogEntries,
});
}

console.log(`Release ${version} created successfully.`);
};

main();
87 changes: 87 additions & 0 deletions scripts/release.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#!/bin/bash

set -e

info() {
echo -e "\033[1;34m$1\033[0m"
}

step() {
echo ""
info "$1"
}

if [ ! -z "$RELEASE_DRY_RUN" ]; then
echo "Dry run mode is enabled"
fi

info "Starting the release process"

step "make install"
make install

step "make build"
make build

step "manual tests: Run the EE tests"
echo "Copy the the packages folder content inside the node_modules of ra-enterprise, then run a full build and run the tests"
echo "Tip: You can use the 'copy-ra-oss-packages-to-ee.sh' script if you have it"
echo "Press Enter when this is done"
read

step "manual tests: Run the demos"
echo "Test the 3 demos (simple, e-commerce, crm): check console & UI"
echo "Press Enter when this is done"
read

step "manual task: Update the create-react-admin dependencies"
echo "[Minor version only] Update the dependencies to RA packages in the create-react-admin templates && commit"
echo "Press Enter when this is done"
read

step "lerna version"
./node_modules/.bin/lerna version --force-publish --no-push

# Get the version from package.json
npm_package_version=$(jq -r '.version' ./packages/react-admin/package.json)

step "update-changelog"
yarn run update-changelog ${npm_package_version}
echo "Please review the ./CHANGELOG.md file and update it if needed."
echo "Press Enter when this is done"
read
if [ -z "$RELEASE_DRY_RUN" ]; then
echo "Committing the changelog"
git add CHANGELOG.md
git commit -m "Update changelog for version ${npm_package_version}"
fi

step "git push"
if [ -z "$RELEASE_DRY_RUN" ]; then
echo "Pushing commits and tags to git"
git push origin HEAD
git push origin --tags
else
echo "dry mode -- skipping git push"
fi

step "lerna publish"
if [ -z "$RELEASE_DRY_RUN" ]; then
# explicitly publish packages where the latest version is not present in the registry
./node_modules/.bin/lerna publish from-package
else
echo "dry mode -- skipping lerna publish"
fi

step "update-milestones"
yarn run update-milestones ${npm_package_version}

step "create-github-release"
yarn run create-github-release ${npm_package_version}

step "manual step: Update the documentation"
echo "You can use the 'copy-ra-oss-docs.sh' script if you have it"
echo "Press Enter when this is done"
read

step "The release is done! 🎉"
Loading

0 comments on commit f9a814e

Please sign in to comment.