wonton
wonton

Reputation: 8307

How do I create major and minor tags for components using release-please?

I have a monorepo with multiple components that I would like to version separately with unpinned major and minor versions.

My directory is like

packages/
   package1/
   package2/

and each package is versioned separately using include_component_in_tag which creates individual tags like package1-v2.1.1 and package2-v3.2.2.

I would like unpinned major/minor tags for these components as well such as package1-v2 and package2-v3.2. This is so the consumers of these packages can use say package2-v3.2 and expect all bugfixes to be automatically pulled in.

I can do this easily for the root package using the method described in https://github.com/googleapis/release-please-action?tab=readme-ov-file#creating-majorminor-tags

This method however does not seem to extend to components within a monorepo. What is the best way to go about accomplishing this?

Upvotes: 0

Views: 11

Answers (1)

wonton
wonton

Reputation: 8307

As far as I can tell, there does not exist a native way to easily accomplish this so I wrote my own implementation.

  steps:
    - name: release please
      uses: googleapis/release-please-action@v4
      id: release
    - uses: actions/checkout@v4
    - name: tag component major and minor versions
      if: ${{ steps.release.outputs.release_created }}
      uses: actions/github-script@v7
      env:
        release_output: ${{ toJSON(steps.release.outputs) }}
      with:
        result-encoding: string
        script: |
          await exec.exec('git config user.name mybotusername')
          await exec.exec('git config user.email [email protected]')
          
          const outputs = JSON.parse(process.env.release_output);
          // for some reason pathsReleased is a string and not an array within the JSON
          const pathsReleased = JSON.parse(outputs.paths_released);
          for (let i = 0; i < pathsReleased.length; i++) {
            let releasePath = pathsReleased[i];
            if (releasePath === ".") {
                  // ignore root package
                  continue;
            }
            const major = outputs[`${releasePath}--major`];
            const minor = outputs[`${releasePath}--minor`];
            const package_name = outputs[`${releasePath}--name`].split(":")[0];
            
            console.log(`Creating ${major}.${minor} releases for ${package_name}`);

            const cmdOpts = {
              ignoreReturnCode: true
            };
            await exec.exec('git', ["tag", "-d", `${package_name}-v${major}`], cmdOpts);
            await exec.exec('git', ["tag", "-d", `${package_name}-v${major}.${minor}`], cmdOpts);
            await exec.exec('git', ["push", "origin", `:${package_name}-v${major}`], cmdOpts)
            await exec.exec('git', ["push", "origin", `:${package_name}-v${major}.${minor}`], cmdOpts)
            await exec.exec('git', ["tag", "-a", `${package_name}-v${major}`, "-m", `Release v${major}`])
            await exec.exec('git', ["tag", "-a", `${package_name}-v${major}.${minor}`, "-m", `Release v${major}.${minor}`])
            await exec.exec('git', ["push", "origin", `${package_name}-v${major}`])
            await exec.exec('git', ["push", "origin", `${package_name}-v${major}.${minor}`])
          }

This implementation leverages the paths_released output from the release-please step to find the packages that have releases, and then uses the individual package outputs to create and push major and minor tags for each package.

Upvotes: 0

Related Questions