Skip to content

Commit

Permalink
feat: filter for lerna tags in independent mode (#267)
Browse files Browse the repository at this point in the history
* feat: filter for lerna tags in independent mode

* feat: improve logging

* chore: execute Prettier linting

Co-authored-by: starptech <deusdustin@gmail.com>
  • Loading branch information
ghiscoding and StarpTech committed Jul 20, 2022
1 parent 5e420fd commit 8c3cdb3
Show file tree
Hide file tree
Showing 12 changed files with 87 additions and 19 deletions.
4 changes: 4 additions & 0 deletions packages/core/src/models/interfaces.ts
Expand Up @@ -237,6 +237,10 @@ export interface UpdateCollectorOptions {
/** Ref to use when querying git, defaults to most recent annotated tag */
since?: string;

/** are we using Lerna independent mode? */
isIndependent?: boolean;

/** are we using conventional commits? */
conventionalCommits?: boolean;
conventionalGraduate?: boolean;
excludeDependents?: boolean;
Expand Down
Expand Up @@ -74,7 +74,29 @@ describe('collectUpdates()', () => {
name: 'package-standalone',
}),
]);
expect(hasTags).toHaveBeenLastCalledWith(execOpts);
expect(hasTags).toHaveBeenLastCalledWith(execOpts, '');
expect(describeRefSync).toHaveBeenLastCalledWith(execOpts, undefined, false);
expect(makeDiffPredicate).toHaveBeenLastCalledWith('v1.0.0', execOpts, undefined);
});

it('returns node with changes in independent mode', () => {
changedPackages.add('package-standalone');

const graph = buildGraph();
const pkgs = graph.rawPackageList;
const execOpts = { cwd: '/test', match: '*@*' };
// require("console").dir(graph, { compact: false });

const updates = collectUpdates(pkgs, graph, execOpts, {
isIndependent: true,
});

expect(updates).toEqual([
expect.objectContaining({
name: 'package-standalone',
}),
]);
expect(hasTags).toHaveBeenLastCalledWith(execOpts, '*@*');
expect(describeRefSync).toHaveBeenLastCalledWith(execOpts, undefined, false);
expect(makeDiffPredicate).toHaveBeenLastCalledWith('v1.0.0', execOpts, undefined);
});
Expand Down
Expand Up @@ -17,6 +17,12 @@ describe('hasTags()', () => {
expect(childProcess.execSync).toHaveBeenLastCalledWith('git', ['tag'], { cwd: 'test' });
});

it('calls `git tag` with --list pattern', () => {
hasTags({ cwd: 'test' }, '*@*');

expect(childProcess.execSync).toHaveBeenLastCalledWith('git', ['tag', '--list', '*@*'], { cwd: 'test' });
});

it('returns true when tags exist', () => {
expect(hasTags()).toBe(true);
});
Expand Down
21 changes: 17 additions & 4 deletions packages/core/src/utils/collect-updates/collect-updates.ts
@@ -1,5 +1,5 @@
import log from 'npmlog';
import { ExecOpts, UpdateCollectorOptions } from '../../models';
import { DescribeRefOptions, ExecOpts, UpdateCollectorOptions } from '../../models';
import { Package } from '../../package';
import { PackageGraph } from '../../package-graph';

Expand All @@ -23,7 +23,7 @@ export function collectUpdates(
commandOptions: UpdateCollectorOptions,
gitDryRun = false
) {
const { forcePublish, conventionalCommits, conventionalGraduate, excludeDependents } = commandOptions;
const { forcePublish, conventionalCommits, conventionalGraduate, excludeDependents, isIndependent } = commandOptions;

// If --conventional-commits and --conventional-graduate are both set, ignore --force-publish
const useConventionalGraduate = conventionalCommits && conventionalGraduate;
Expand All @@ -37,10 +37,23 @@ export function collectUpdates(
: new Map(filteredPackages.map(({ name }) => [name, packageGraph.get(name)]));

let committish = commandOptions.since;
const tagPattern = isIndependent ? '*@*' : '';

if (hasTags(execOpts, tagPattern)) {
const describeOptions: DescribeRefOptions = {
...execOpts,
};

if (isIndependent) {
describeOptions.match = tagPattern;
}

if (hasTags(execOpts)) {
// describe the last annotated tag in the current branch
const { sha, refCount, lastTagName } = describeRefSync(execOpts, commandOptions.includeMergedTags, gitDryRun);
const { sha, refCount, lastTagName } = describeRefSync(
describeOptions,
commandOptions.includeMergedTags,
gitDryRun
);
// TODO: warn about dirty tree?

if (refCount === '0' && forced.size === 0 && !committish) {
Expand Down
11 changes: 9 additions & 2 deletions packages/core/src/utils/collect-updates/lib/has-tags.ts
Expand Up @@ -5,13 +5,20 @@ import { execSync } from '../../../child-process';
/**
* Determine if any git tags are reachable.
* @param {import("@lerna/child-process").ExecOpts} opts
* @param {string} tagPattern
*/
export function hasTags(opts) {
export function hasTags(opts, tagPattern: string) {
log.silly('hasTags', '');
let result = false;
const args = ['tag'];

if (tagPattern) {
log.verbose('hasTags', `filter for tags with '${tagPattern}' pattern`);
args.push('--list', tagPattern);
}

try {
result = !!execSync('git', ['tag'], opts);
result = !!execSync('git', args, opts);
} catch (err: any) {
log.warn('ENOTAGS', 'No git tags were reachable from this branch!');
log.verbose('hasTags error', err);
Expand Down
16 changes: 12 additions & 4 deletions packages/core/src/utils/describe-ref.ts
Expand Up @@ -48,8 +48,12 @@ function describeRef(
return promise.then(({ stdout } = { stdout: '' }) => {
const result = parse(stdout, options.cwd);

log.verbose('git-describe', '%j => %j', options?.match, stdout);
log.silly('git-describe', 'parsed => %j', result);
if (options?.match) {
log.verbose('git-describe', '%j => %j', options?.match, stdout);
}
if (stdout) {
log.silly('git-describe', 'parsed => %j', result);
}

return result;
});
Expand All @@ -63,8 +67,12 @@ function describeRefSync(options: DescribeRefOptions = {}, includeMergedTags?: b
const stdout = execSync('git', getArgs(options, includeMergedTags), options, gitDryRun);
const result = parse(stdout, options.cwd);

// only called by collect-updates with no matcher
log.silly('git-describe.sync', '%j => %j', stdout, result);
if (options?.match) {
log.verbose('git-describe.sync', '%j => %j', options?.match, stdout);
}
if (stdout) {
log.silly('git-describe', 'parsed => %j', result);
}

return result;
}
Expand Down
2 changes: 2 additions & 0 deletions packages/exec/src/exec-command.ts
Expand Up @@ -61,6 +61,8 @@ export class ExecCommand extends Command<ExecCommandOption & FilterOptions> {

let chain: Promise<any> = Promise.resolve();

this.options.isIndependent = this.project.isIndependent();

chain = chain.then(() => getFilteredPackages(this.packageGraph, this.execOpts, this.options));
chain = chain.then((filteredPackages: Package[]) => {
this.filteredPackages = filteredPackages;
Expand Down
1 change: 1 addition & 0 deletions packages/list/src/list-command.ts
Expand Up @@ -20,6 +20,7 @@ export class ListCommand extends Command<ListCommandOption & FilterOptions> {
}

async initialize() {
this.options.isIndependent = this.project.isIndependent();
const filteredPackages = await getFilteredPackages(this.packageGraph, this.execOpts, this.options);
this.result = listable.format(filteredPackages, this.options);
}
Expand Down
1 change: 1 addition & 0 deletions packages/optional-cmd-common/src/models/index.ts
Expand Up @@ -6,6 +6,7 @@ export interface FilterOptions {
ignore: string[];
private: boolean;
since: string;
isIndependent: boolean;
continueIfNoMatch: boolean;
excludeDependents: boolean;
includeDependents: boolean;
Expand Down
5 changes: 4 additions & 1 deletion packages/publish/src/publish-command.ts
Expand Up @@ -365,6 +365,8 @@ export class PublishCommand extends Command<PublishCommandOption> {
}
});

const isIndependent = this.project.isIndependent();

// find changed packages since last release, if any
chain = chain.then(() =>
collectUpdates(
Expand All @@ -377,6 +379,7 @@ export class PublishCommand extends Command<PublishCommandOption> {
ignoreChanges,
forcePublish,
includeMergedTags,
isIndependent,
// private packages are never published, don't bother describing their refs.
} as UpdateCollectorOptions,
this.options.gitDryRun
Expand All @@ -394,7 +397,7 @@ export class PublishCommand extends Command<PublishCommandOption> {
return `${nextVersion}-${preid}.${Math.max(0, refCount - 1)}+${sha}`;
};

if (this.project.isIndependent()) {
if (isIndependent) {
// each package is described against its tags only
chain = chain.then((updates) =>
pMap(updates, (node: Package) =>
Expand Down
2 changes: 2 additions & 0 deletions packages/run/src/run-command.ts
Expand Up @@ -60,6 +60,8 @@ export class RunCommand extends Command<RunCommandOption & FilterOptions> {
this.options.log = this.logger;
}

this.options.isIndependent = this.project.isIndependent();

chain = chain.then(() => getFilteredPackages(this.packageGraph!, this.execOpts, this.options));
chain = chain.then((filteredPackages: Package[]) => {
this.packagesWithScript =
Expand Down
13 changes: 6 additions & 7 deletions packages/version/src/version-command.ts
Expand Up @@ -150,7 +150,8 @@ export class VersionCommand extends Command<VersionCommandOption> {
}

async initialize() {
if (!this.project.isIndependent()) {
const isIndependent = this.project.isIndependent();
if (!isIndependent) {
this.logger.info('current project version', this.project.version ?? '');
}

Expand Down Expand Up @@ -245,12 +246,10 @@ export class VersionCommand extends Command<VersionCommandOption> {
);
}

this.updates = collectUpdates(
this.packageGraph.rawPackageList,
this.packageGraph,
this.execOpts,
this.options as UpdateCollectorOptions
).filter((node) => {
this.updates = collectUpdates(this.packageGraph.rawPackageList, this.packageGraph, this.execOpts, {
...this.options,
isIndependent,
} as UpdateCollectorOptions).filter((node) => {
// --no-private completely removes private packages from consideration
if (node.pkg.private && this.options.private === false) {
// TODO: (major) make --no-private the default
Expand Down

0 comments on commit 8c3cdb3

Please sign in to comment.