gpt4 book ai didi

npm - Bump 版本并从一个分支发布包,但在另一个分支中保留标签

转载 作者:行者123 更新时间:2023-12-04 14:34:09 26 4
gpt4 key购买 nike

我正在将包含许多相互依赖的包的项目迁移到带有 Lerna 的 monorepo 。我们在开发过程中遵循类似 Gitflow workflow 的方法。主要概念是在 develop 分支和从 develop 创建并合并回的所有其他分支(功能、错误修复等)中进行所有源代码更改。只要准备好新版本的包,我们就通过 npm publishyarn publish 发布它,然后将其合并到 master 分支并通过以下方式手动标记它:

$ git checkout develop

对源代码进行一些更改,包括版本碰撞...

$ git add -A
$ git commit -m "Make some changes and version bump."
$ git checkout master
$ git merge --no-ff develop -m "Version 0.14.1."
$ git tag -a 0.14.1 -m "Version 0.14.1."

现在我想用 Lerna 管理所有包来实现同样的事情。查看文档,我指出 publish 命令依赖于 version 命令,而 changed 命令又在幕后使用 include-merged-tags 命令来检测自最新版本以来包中所做的更改:

List local packages that have changed since the last tagged release



考虑在一个包中的 develop 分支中进行了一些更改(例如 @geoapps/layout )



$ lerna changed

说所有软件包都已更改(这不是我所期望的):
info cli using local version of lerna
lerna notice cli v3.13.1
lerna info Assuming all packages changed
@geoapps/angle
@geoapps/camera-scene-mode-switcher
...
@geoapps/tracer
@geoapps/vector
lerna success found 39 packages ready to publish

我猜这是因为 Lerna 在 develop 分支中寻找标记的提交来进行比较,但在那里什么也没找到。如果我将源代码更改提交到 master 分支



然后 Lerna 在单个 @geoapps/layout 包中正确检测它们:

$ git checkout master
$ lerna changed
info cli using local version of lerna
lerna notice cli v3.13.1
lerna info Looking for changed packages since 0.14.1
@geoapps/layout
lerna success found 1 package ready to publish

但是在 master 分支中进行更改也不是我想要做的。 ojit_a 是我尝试使用的另一个选项,但似乎只有在标记提交也是 develop 分支历史的一部分时才有效:
$ git checkout develop
$ git merge --no-ff master -m "Sync with master."



$ lerna changed --include-merged-tags
info cli using local version of lerna
lerna notice cli v3.13.1
lerna info Looking for changed packages since 0.14.1
@geoapps/layout
lerna success found 1 package ready to publish

由于在 master 分支中标记的所有源代码更改都存在于 develop 分支中,我想知道是否可以强制 Lerna 将 develop 分支中所做的更改不是与来自 master 的标记提交进行比较,而是与它们的父提交( 0.14.1^2 )也属于 develop 进行比较。是否可以?

环境:
$ node --version
v10.15.0
$ npm --version
6.9.0
$ yarn --version
1.15.2
$ lerna --version
3.13.1

最佳答案

Lerna 核心开发人员 says Lerna 不适合与 Gitflow 工作流一起使用。说多了,是prohibited发布从特定提交(在另一个分支中标记提交)检测其更改的包。最新的标记版本应该属于进行更改的同一分支。

牢记它以及我们希望继续使用 Gitflow,我决定修补 Lerna 以实现所需的行为。刚刚created git patch并使用 Lerna 将其放置在我的项目的根目录中。

lerna-version-since.patch

diff --git a/commands/version/command.js b/commands/version/command.js
index da9b1c00..3c5e19e2 100644
--- a/commands/version/command.js
+++ b/commands/version/command.js
@@ -104,6 +104,11 @@ exports.builder = (yargs, composed) => {
requiresArg: true,
defaultDescription: "alpha",
},
+ since: {
+ describe: "Look for changes since specified commit instead of last tagged release",
+ type: "string",
+ requiresArg: true,
+ },
"sign-git-commit": {
describe: "Pass the `--gpg-sign` flag to `git commit`.",
type: "boolean",

如果在 commands/version/command.js 中发生了变化那么我们可能会更新补丁。为了应用补丁,应该运行以下命令:

$ git apply -p3 --directory node_modules/@lerna/version lerna-version-since.patch

修补 Lerna 后,现在可以在 develop 中进行碰撞和发布在 master 中分支并标记一个版本.为了使事情更简单,我编写了一个名为 lerna-gitflow.js 的脚本。这让一切都自动进行。这是 package.json 的脚本部分:
"scripts": {
"publish:major": "./lerna-gitflow.js publish major",
"publish:minor": "./lerna-gitflow.js publish minor",
"publish:patch": "./lerna-gitflow.js publish patch",
"changes": "./lerna-gitflow.js changes",
"postinstall": "./lerna-gitflow.js patch"
}

所有这些 publish:*changes命令应该从开发分支运行(默认为 develop)。
changes命令仅显示自发布分支中的最新发布标记(默认为 develop)以来开发分支( master )中更改的包。
publish命令做了两件事:
  • 更新版本 package.json更改包的文件,在根目录 package.jsonlerna.json并将它们提交给 develop本地分支(可以通过运行单独完成,例如, ./lerna-gitflow.js version patch );
  • 将更改的包从 develop 发布到 npm 注册表分支,然后将更改合并到 master没有快进的分支并在那里标记一个新版本(也可以通过运行 ./lerna-gitflow.js publish --skip-version 单独完成)。
  • postinstall脚本试图在任何 npm install 上修补 Lerna或 yarn install调用其他需要的更改以使一切正常工作将丢失。

    lerna-gitflow.js
    #!/usr/bin/env node
    const path = require('path');
    const yargs = require('yargs');
    const execa = require('execa');
    const jsonfile = require('jsonfile');

    const noop = () => {};

    async function lernaCommand(command, options) {
    const { devBranch } = options;
    const branch = await getCurrentBranch();
    if (branch !== devBranch) {
    return Promise.reject(
    `You should be in "${devBranch}" branch to detect changes but current branch is "${branch}".`
    );
    }
    const latestVersion = await getLatestVersion();

    const bumpVersion = async bump => {
    await lernaVersion(latestVersion, bump);
    const version = await getLernaVersion();
    const packageJsonPath = path.resolve(__dirname, 'package.json');
    const packageJson = await jsonfile.readFile(packageJsonPath);
    packageJson.version = version;
    await jsonfile.writeFile(packageJsonPath, packageJson, { spaces: 2 });
    await exec('git', ['add', '-A']);
    await exec('git', ['commit', '-m', 'Version bump.']);
    return version;
    };

    const reject = e => {
    if (typeof e === 'string') {
    return Promise.reject(e);
    }
    return Promise.reject('Unable to detect any changes in packages, probably nothing has changed.');
    };

    switch (command) {
    case 'publish': {
    const { bump, skipVersion, releaseBranch } = options;
    if (releaseBranch === devBranch) {
    return Promise.reject('Release and development branches can\'t be the same.');
    }
    try {
    const version = skipVersion ? await getLernaVersion() : await bumpVersion(bump);
    await lernaPublish(latestVersion, version);
    await exec('git', ['checkout', releaseBranch]);
    await exec('git', ['merge', '--no-ff', devBranch, '-m', `Version ${version}.`]);
    await exec('git', ['tag', '-a', version, '-m', `Version ${version}.`]);
    await exec('git', ['checkout', devBranch]);
    }
    catch (e) {
    return reject(e);
    }
    break;
    }

    case 'version': {
    const { bump } = options;
    try {
    await bumpVersion(bump);
    }
    catch (e) {
    return reject(e);
    }
    break;
    }

    case 'changed': {
    try {
    await lernaChanged(latestVersion);
    }
    catch (e) {
    return reject(e);
    }
    break;
    }
    }
    }

    async function lernaPublish(since, version) {
    if (since === version) {
    return Promise.reject(`Unable to publish packages with same version ${version}.`);
    }
    return exec('lerna', ['publish', '--since', since, version, '--no-push', '--no-git-tag-version', '--yes']);
    }

    async function lernaVersion(since, bump) {
    return exec('lerna', ['version', '--since', since, bump, '--no-push', '--no-git-tag-version', '--yes']);
    }

    async function lernaChanged(since) {
    return exec('lerna', ['changed', '--since', since]);
    }

    async function patch() {
    try {
    await exec('git', ['apply', '-p3', '--directory', 'node_modules/@lerna/version', 'lerna-version-since.patch']);
    }
    catch (e) {
    return Promise.reject('Lerna Gitflow patch is not applied (probably, it\'s already applied before).');
    }
    }

    async function getCurrentBranch() {
    const { stdout } = await exec('git', ['branch']);
    const match = stdout.match(/\* ([\S]+)/);
    if (match === null) {
    return Promise.reject('Unable to detect current git branch.');
    }
    return match[1];
    }

    async function getLatestTaggedCommit() {
    const { stdout } = await exec('git', ['rev-list', '--tags', '--max-count', 1]);
    if (!stdout) {
    return Promise.reject('Unable to find any tagged commit.');
    }
    return stdout;
    }

    async function getLatestVersion() {
    const commit = await getLatestTaggedCommit();
    const { stdout } = await exec('git', ['describe', '--tags', commit]);
    return stdout;
    }

    async function getLernaVersion() {
    const lernaJson = await jsonfile.readFile(path.resolve(__dirname, 'lerna.json'));
    return lernaJson.version;
    }

    function exec(cmd, args, opts) {
    console.log(`$ ${cmd} ${args.join(' ')}`);
    const promise = execa(cmd, args, opts);
    promise.stdout.pipe(process.stdout);
    promise.stderr.pipe(process.stderr);
    return promise;
    }

    yargs
    .wrap(null)
    .strict(true)
    .help(true, 'Show help')
    .version(false)
    .fail((msg, error) => {
    console.error(error);
    if (msg) {
    console.error(msg);
    }
    })
    .demandCommand()
    .command(
    'publish <bump>',
    'Bump and commit packages\' in development branch, then publish, merge into and tag in release branch',
    yargs => yargs
    .positional('bump', {
    describe: 'Type of version update',
    type: 'string'
    })
    .option('skip-version', {
    describe: 'Skip version bumping and commiting in development branch',
    type: 'boolean',
    default: false
    }),
    opts => lernaCommand('publish', opts)
    )
    .command(
    'version <bump>',
    'Bump and commit packages\' version in development branch',
    yargs => yargs
    .positional('bump', {
    describe: 'Type of version update',
    type: 'string'
    }),
    opts => lernaCommand('version', opts)
    )
    .command(
    'changes',
    'Detect packages changes since latest release',
    noop,
    opts => lernaCommand('changed', opts)
    )
    .command('patch', 'Patch Lerna to use with Gitflow', noop, () => patch())
    .options({
    'dev-branch': {
    describe: 'Name of git development branch',
    type: 'string',
    demandOption: true,
    default: 'develop'
    },
    'release-branch': {
    describe: 'Name of git release branch',
    type: 'string',
    demandOption: true,
    default: 'master'
    }
    })
    .parse();

    关于npm - Bump 版本并从一个分支发布包,但在另一个分支中保留标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55522919/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com