diff --git a/.github/workflows/alpha-npm.yml b/.github/workflows/alpha-npm.yml index 5f3975505..5a32f6c39 100644 --- a/.github/workflows/alpha-npm.yml +++ b/.github/workflows/alpha-npm.yml @@ -46,26 +46,18 @@ jobs: - name: Install dependencies run: npm ci - - name: Build all workspace packages - run: npm run build - - - name: Generate alpha version string and modify packages + - name: Generate alpha prerelease and bump package.json @web5/* versions env: NODE_AUTH_TOKEN: ${{secrets.npm_token}} run: | SHORT_COMMIT_SHA=$(git rev-parse --short HEAD) YYYYMMDD=$(date +'%Y%m%d') - for package in $PACKAGES; do - cd packages/$package - REPO_VERSION=$(node -p "require('./package.json').version") - ALPHA_VERSION="${REPO_VERSION}-alpha-$YYYYMMDD-$SHORT_COMMIT_SHA" - npm version $ALPHA_VERSION --no-git-tag-version - cd ../.. - done + ALPHA_PRERELEASE="alpha-$YYYYMMDD-$SHORT_COMMIT_SHA" + node ./scripts/bump-workspace.mjs --prerelease=$ALPHA_PRERELEASE shell: bash - - name: Bump package.json @web5/* dependency versions - run: node ./scripts/bump-workspace.mjs + - name: Build all workspace packages + run: npm run build - name: Publish selected @web5/* packages env: @@ -73,7 +65,6 @@ jobs: run: | for package in $PACKAGES; do cd packages/$package - cat package.json npm publish --tag alpha --no-git-tag-version --access public cd ../.. done diff --git a/scripts/bump-workspace.mjs b/scripts/bump-workspace.mjs index bbefa62ef..9a12f796a 100644 --- a/scripts/bump-workspace.mjs +++ b/scripts/bump-workspace.mjs @@ -35,19 +35,33 @@ async function getWorkspaces() { } /** - * Retrieves the versions of packages for the given paths. + * Retrieves the versions of packages for the given paths, optionally appending + * a prerelease tag to the versions. + * + * This function reads the package versions from the specified paths and builds + * an object mapping package names to their corresponding versions. If a + * prerelease value is provided, it will be appended to the version string. * * @param {string[]} paths - An array of paths to the package.json files. + * @param {string} [prerelease] - An optional prerelease tag to append to the + * versions (e.g., 'alpha', 'beta'). * @returns {Record} An object mapping package names to their * corresponding versions. */ -async function getPackageVersions(paths) { +async function getPackageVersions(paths, prerelease) { const versions = {}; for (const path of paths) { const packageJson = await PackageJson.load(path); + // Get the package name (e.g., '@web5/common') const packageName = packageJson.content.name; - const version = packageJson.content.version; + // Get the current major.minor.patch version (e.g., '0.2.0'). + const [currentVersion] = packageJson.content.version.split('-'); + // Prefix the prerelease value, if any, with a hyphen. + const versionSuffix = prerelease ? `-${prerelease}` : ''; + // If a prelease value is defined, append it to the version string (e.g., '0.2.0-alpha'). + const version = currentVersion + versionSuffix; + // Add to the versions object. versions[packageName] = version; } @@ -55,7 +69,46 @@ async function getPackageVersions(paths) { } /** - * Updates dependencies of the workspaces to the latest versions. + * Parses the command-line arguments provided to the script and returns + * them as a configuration object. + * + * The function expects arguments in the format of '--key=value' and extracts + * them into key-value pairs stored within the configuration object. This allows + * for flexible configuration of the script's behavior via the command line. + * + * @param {string[]} argv - An array of command-line arguments passed to the script. + * @returns {Record} An object mapping argument names to their + * corresponding values. + * + * @example + * + * const config = parseCliArguments(['--prerelease=alpha']); + * // Returns: { prerelease: 'alpha' } + */ +function parseCliArguments(argv) { + const config = {}; + argv.forEach((arg) => { + if (arg.startsWith('--')) { + // Remove the '--' prefix. + const argWithoutPrefix = arg.substring(2); + // Split argName=argValue. + const [argName, argValue] = argWithoutPrefix.split('='); + // Store in config object. + config[argName] = argValue; + } + }); + + return config; +} + +/** + * Updates dependencies of the workspaces to the latest versions and updates + * the version of the package itself. + * + * This function iterates through the provided workspaces and updates both + * regular dependencies and devDependencies to their latest versions. Additionally, + * it updates the version of the package itself according to the corresponding + * entry in the `packageVersions` object. * * @param {string[]} workspaces - An array of workspace paths. * @param {Record} packageVersions - An object mapping package @@ -65,6 +118,7 @@ async function updateDependencies(workspaces, packageVersions) { for (const workspace of workspaces) { const packageJson = await PackageJson.load(workspace); + const version = packageVersions[packageJson.content.name]; const dependencies = packageJson.content.dependencies ?? []; const devDependencies = packageJson.content.devDependencies ?? []; @@ -80,7 +134,7 @@ async function updateDependencies(workspaces, packageVersions) { } // Write changes, if any, to each `package.json` file. - packageJson.update({ dependencies, devDependencies }); + packageJson.update({ version, dependencies, devDependencies }); await packageJson.save(); } } @@ -91,8 +145,9 @@ async function updateDependencies(workspaces, packageVersions) { * versions, if any, are updated. */ async function main() { + const config = parseCliArguments(process.argv); const workspaces = await getWorkspaces(); - const packageVersions = await getPackageVersions(workspaces); + const packageVersions = await getPackageVersions(workspaces, config.prerelease); await updateDependencies(workspaces, packageVersions); }