Skip to content

Commit 95e7a05

Browse files
authored
Ensure name is properly used when creating scheduled release (#12)
1 parent 032c99f commit 95e7a05

File tree

4 files changed

+68
-11
lines changed

4 files changed

+68
-11
lines changed

README.md

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -125,13 +125,23 @@ linear-release update --stage="in review" --release-version="1.2.0"
125125

126126
### CLI Options
127127

128-
| Option | Commands | Description |
129-
| ------------------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
130-
| `--name` | `sync` | Custom release name. Defaults to short commit hash. |
131-
| `--release-version` | `sync`, `complete`, `update` | Release version identifier. For `sync`, defaults to short commit hash. For `complete` and `update`, if omitted, targets the most recent started release. |
132-
| `--stage` | `update` | Target deployment stage (required for `update`) |
133-
| `--include-paths` | `sync` | Filter commits by changed file paths |
134-
| `--json` | `sync`, `complete`, `update` | Output result as JSON |
128+
| Option | Commands | Description |
129+
| ------------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
130+
| `--name` | `sync` | Custom release name. Continuous pipelines: used when creating a release. Scheduled pipelines: used only when `sync` creates a new release; existing release names are preserved. Ignored (with warning) for `complete` and `update`. |
131+
| `--release-version` | `sync`, `complete`, `update` | Release version identifier. For `sync`, defaults to short commit hash. For `complete` and `update`, if omitted, targets the most recent started release. |
132+
| `--stage` | `update` | Target deployment stage (required for `update`) |
133+
| `--include-paths` | `sync` | Filter commits by changed file paths |
134+
| `--json` | `sync`, `complete`, `update` | Output result as JSON |
135+
136+
### Command Targeting
137+
138+
| Command | With `--release-version` | Without `--release-version` |
139+
| ---------- | -------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
140+
| `sync` | Targets matching version or creates a release for that version | Continuous pipelines create a release with short SHA name/version. Scheduled pipelines use the current started/planned flow. |
141+
| `update` | Updates that exact release version | Updates latest started release, or latest planned release if no started release exists |
142+
| `complete` | Completes that exact release version | Completes latest started release |
143+
144+
For scheduled pipelines, prefer always passing `--release-version` in CI, especially when releases overlap.
135145

136146
### JSON Output
137147

@@ -168,6 +178,13 @@ Path patterns can also be configured in your pipeline settings in Linear. If bot
168178
4. **Detects pull request numbers** from commit messages (e.g., `Merge pull request #42`)
169179
5. **Syncs to Linear** creating or updating the release with linked issues
170180

181+
## Troubleshooting
182+
183+
- **Unexpected release was updated/completed**: pass `--release-version` explicitly so the command does not target the latest started/planned release.
184+
- **No release created by `sync`**: if no commits match the computed range (or path filters), `sync` returns `{"release":null}`.
185+
- **Stage update fails**: verify stage name exactly. If stage names normalize to the same value, use the exact stage name to avoid ambiguity.
186+
- **`--name` seems ignored**: `--name` only applies to `sync`; `complete` and `update` ignore it and print a warning.
187+
171188
## License
172189

173190
Licensed under the [MIT License](./LICENSE).

src/args.test.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { describe, expect, it } from "vitest";
2-
import { parseCLIArgs } from "./args";
2+
import { getCLIWarnings, parseCLIArgs } from "./args";
33

44
describe("parseCLIArgs", () => {
55
it("defaults command to sync when no positional given", () => {
@@ -83,4 +83,19 @@ describe("parseCLIArgs", () => {
8383
it("throws on unknown flags (strict mode)", () => {
8484
expect(() => parseCLIArgs(["--unknown-flag"])).toThrow();
8585
});
86+
87+
it("returns warning when --name is used with update", () => {
88+
const result = parseCLIArgs(["update", "--name", "Release 1.2.0"]);
89+
expect(getCLIWarnings(result)).toEqual(['--name is ignored for "update" command; it only applies to "sync"']);
90+
});
91+
92+
it("returns warning when --name is used with complete", () => {
93+
const result = parseCLIArgs(["complete", "--name", "Release 1.2.0"]);
94+
expect(getCLIWarnings(result)).toEqual(['--name is ignored for "complete" command; it only applies to "sync"']);
95+
});
96+
97+
it("returns no warning when --name is used with sync", () => {
98+
const result = parseCLIArgs(["sync", "--name", "Release 1.2.0"]);
99+
expect(getCLIWarnings(result)).toEqual([]);
100+
});
86101
});

src/args.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
import { parseArgs } from "node:util";
22

3-
export function parseCLIArgs(argv: string[]) {
3+
export type ParsedCLIArgs = {
4+
command: string;
5+
releaseName?: string;
6+
releaseVersion?: string;
7+
stageName?: string;
8+
includePaths: string[];
9+
jsonOutput: boolean;
10+
};
11+
12+
export function parseCLIArgs(argv: string[]): ParsedCLIArgs {
413
const { values, positionals } = parseArgs({
514
args: argv,
615
options: {
@@ -28,3 +37,13 @@ export function parseCLIArgs(argv: string[]) {
2837
jsonOutput: values.json ?? false,
2938
};
3039
}
40+
41+
export function getCLIWarnings(args: ParsedCLIArgs): string[] {
42+
const warnings: string[] = [];
43+
44+
if (args.releaseName && args.command !== "sync") {
45+
warnings.push(`--name is ignored for "${args.command}" command; it only applies to "sync"`);
46+
}
47+
48+
return warnings;
49+
}

src/index.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
PullRequestSource,
1616
RepoInfo,
1717
} from "./types";
18-
import { parseCLIArgs } from "./args";
18+
import { getCLIWarnings, parseCLIArgs } from "./args";
1919
import { log, setStderr } from "./log";
2020
import { pluralize } from "./util";
2121
import { buildUserAgent } from "./user-agent";
@@ -77,6 +77,7 @@ try {
7777
process.exit(1);
7878
}
7979
const { command, releaseName, releaseVersion, stageName, includePaths, jsonOutput } = parsedArgs;
80+
const cliWarnings = getCLIWarnings(parsedArgs);
8081
if (jsonOutput) {
8182
setStderr(true);
8283
}
@@ -85,11 +86,16 @@ const logEnvironmentSummary = () => {
8586
log("Using access key authentication");
8687

8788
if (releaseName) {
88-
log(`Using custom release name: ${releaseName}`);
89+
if (command === "sync") {
90+
log(`Using custom release name: ${releaseName}`);
91+
}
8992
}
9093
if (releaseVersion) {
9194
log(`Using custom release version: ${releaseVersion}`);
9295
}
96+
for (const warning of cliWarnings) {
97+
log(`Warning: ${warning}`);
98+
}
9399

94100
log(`Running in ${process.env.NODE_ENV === "development" ? "development" : "production"} mode`);
95101
};

0 commit comments

Comments
 (0)