DEV Community

Kinga
Kinga

Posted on • Edited on

Rush and changelog generation - Part 3

The source code is on GitHub so I will only make a quick walk-through here.

The script

  • Get the last commit message (including hash). Following conventional commits specification, decide whether version number should be increased. If yes:
  • calculate the next version and
  • get the list of changed projects. For each of the changed projects get the last two commits and:
    • ensure that the hash of project last commit is equal to the hash of the last commit (in case rush indicates the change, but the files were not included in the last commit) and
    • ensure that the last two commit messages are not equal.
    • If the above is true, generate change files based on the commits. Append the change file to the last commit using --amend

Importing modules installed by autoinstaller

Importing modules installed by the rush-changemanager autoinstaller requires a path to the node_modules.

//...
const node_modules = path.join(__dirname, '..', 'autoinstallers/rush-changemanager/node_modules');
const rushLib = require(path.join(node_modules, '@microsoft/rush-lib'));
const rushCore = require(path.join(node_modules, '@rushstack/node-core-library'));
const gitlog = require(path.join(node_modules, 'gitlog')).default;
const recommendedBump = require(path.join(node_modules, 'recommended-bump'));
Enter fullscreen mode Exit fullscreen mode

Rush custom commands: execute custom script with autoinstaller dependencies.

Recommended bump

To generate change files for commit types fix:, feat: and BREAKING CHANGE (if the commit has a footer BREAKING CHANGE:, or appends a ! after the type/scope), retrieve the last commit using gitlog, and parse it using recommendedBump.

const options = {
    repo: repoPath,
    file: repoPath,
    number: 1,
    fields: ["subject", "body", "rawBody", "authorEmail", "hash"]
}
const lastCommit = gitlog(options);
//fix, feat or BREAKING?
const { increment } = recommendedBump([lastCommit[0].rawBody]);
Enter fullscreen mode Exit fullscreen mode

Get changed projects

If the last commit should trigger change file generation, retrieve the names and folder paths of the changed projects using ProjectChangeAnalyzer.

Important: ProjectChangeAnalyzer API is provided as a preview and may change. Use at your own risk.

const projectAnalyzer = new rushLib.ProjectChangeAnalyzer(rushConfiguration);
const terminal = new rushCore.Terminal(new rushCore.ConsoleTerminalProvider({ verboseEnabled: false }));

const changedProjects  = await projectAnalyzer.getChangedProjectsAsync({
//...
});
Enter fullscreen mode Exit fullscreen mode

Are the changed projects included in the last commit?

Retrieve the last two commits for each changed projects. This allows verifying that:

  • the specific project was included in the last commit, and
  • the last two commit messages are different.

If everything checks, the change files are generated using ChangeManager class. After their content is set based on the parsed commit messages, they are committed to the repo.

async function getChangedProjectNamesAsync(rushConfiguration) {
    const changedProjects  = await projectAnalyzer.getChangedProjectsAsync({ 
        targetBranchName: getCurrentBranch() , //detect current branch
        //...
});

    changedProjects.forEach(project => {
        rushProjects.set(project.packageName, project.projectFolder);
    });
    return rushProjects;    
}

//...
getChangedProjectNamesAsync(rushConfiguration).then((rushProjects) => {
    rushProjects.forEach((value, key) => {
    const result = parseRecentCommits(key, value, lastCommitInfo, rushConfiguration.rushJsonFolder);
    if (result) { 
        generateChangeFile(rushConfiguration, result);
        executeCommand(`git add ${rushConfiguration.changesFolder}`);
        executeCommandAsync(`git commit --no-edit --no-verify --amend `);
    }
});
Enter fullscreen mode Exit fullscreen mode

Git hooks

To generate the change files after git commit, use the post-commit git hook, which is is invoked after a commit is made.

common\git-hooks\post-commit

#!/bin/sh
node common/scripts/install-run-rush.js changefiles
Enter fullscreen mode Exit fullscreen mode

Run rush install for Rush to .git/hooks/post-commit

rush install
Enter fullscreen mode Exit fullscreen mode

Testing

When testing, make sure to edit files belonging to a project managed by rush. Changes will not be detected otherwise.

Next steps

This is by far not a finished product. For example, when retrieving changed projects I don't evaluate shouldPublish or versionPolicy.exemptFromRushChange.

Source Code

You may find the source code on GitHub.

Top comments (0)