genbumppush 0.0.4 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -13
- package/dist/bin.mjs +1 -1
- package/dist/index.d.mts +25 -1
- package/dist/index.mjs +1 -1
- package/dist/{release-gwyqzR0C.mjs → release-BdWrsEaL.mjs} +48 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -160,9 +160,11 @@ JSON has no comments and no `defineConfig` typing, so move to `genbumppush.confi
|
|
|
160
160
|
| `github.enabled` | boolean | `false` | Create a GitHub release after push |
|
|
161
161
|
| `github.host` | string | `github.com` | github.com or GHES host |
|
|
162
162
|
| `github.repo` | string | env / remote | `owner/name` |
|
|
163
|
+
| `github.remote` | string | unset | Extra Git remote for dual-host GitHub |
|
|
163
164
|
| `github.tokenEnv` | string | auto | Exact env var name (disables fallbacks) |
|
|
164
165
|
| `github.releaseName` | string | tag | Release title template |
|
|
165
166
|
| `gitlab.enabled` | boolean | `false` | Create a GitLab release after push |
|
|
167
|
+
| `gitlab.remote` | string | unset | Extra Git remote for dual-host GitLab |
|
|
166
168
|
|
|
167
169
|
`{{version}}` is replaced in commit and tag templates. Hooks run through the shell in the repository directory; only use trusted configuration.
|
|
168
170
|
|
|
@@ -291,6 +293,24 @@ Without `tokenEnv`, GitLab tokens resolve from `GENBUMPPUSH_GITLAB_TOKEN`, then
|
|
|
291
293
|
the matching `CHANGELOG.md` section as the release description. If `git.push` is false,
|
|
292
294
|
the provider is rejected because GitLab cannot create a release for an unpublished tag.
|
|
293
295
|
|
|
296
|
+
### Dual-host releases (GitHub + GitLab)
|
|
297
|
+
|
|
298
|
+
GitLab's release API requires `tag_name` to already exist on that project. When `origin` is GitHub and GitLab is a separate remote, set `gitlab.remote` so genbumppush pushes the release branch and tag to GitLab before calling the API:
|
|
299
|
+
|
|
300
|
+
```ts
|
|
301
|
+
export default defineConfig({
|
|
302
|
+
git: { push: true, remote: 'origin' }, // origin → GitHub
|
|
303
|
+
github: { enabled: true },
|
|
304
|
+
gitlab: {
|
|
305
|
+
enabled: true,
|
|
306
|
+
project: 'group/project',
|
|
307
|
+
remote: 'gitlab', // git remote that points at the GitLab project
|
|
308
|
+
},
|
|
309
|
+
});
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
`github.remote` works the same way when GitHub is not the primary remote. Provider remotes must already exist (`git remote add gitlab <url>`); genbumppush fails fast before commit/tag if a configured provider remote is missing. Leave `gitlab.remote` unset when the primary remote already receives the tag (same remote, or a mirror GitLab already has). `--retry-gitlab` / `--retry-github` check the provider remote when one is configured.
|
|
313
|
+
|
|
294
314
|
```yaml
|
|
295
315
|
release:
|
|
296
316
|
image: node:20
|
|
@@ -309,19 +329,20 @@ Keep artifact publication and GitLab release creation in protected, tag-triggere
|
|
|
309
329
|
|
|
310
330
|
## Scenario guide
|
|
311
331
|
|
|
312
|
-
| Scenario
|
|
313
|
-
|
|
|
314
|
-
| Local release
|
|
315
|
-
| CI release
|
|
316
|
-
| Preview only
|
|
317
|
-
| Local commit/tag only
|
|
318
|
-
| Nuxt or Node package
|
|
319
|
-
| npm lockfile
|
|
320
|
-
| Fixed-version monorepo
|
|
321
|
-
| Tauri
|
|
322
|
-
| Custom VERSION file
|
|
323
|
-
| GitHub/npm publication
|
|
324
|
-
| GitLab release
|
|
332
|
+
| Scenario | Recommended setup |
|
|
333
|
+
| ----------------------- | --------------------------------------------------- |
|
|
334
|
+
| Local release | `npm run release`, confirm interactively |
|
|
335
|
+
| CI release | `genbumppush --yes` with protected Git credentials |
|
|
336
|
+
| Preview only | `genbumppush --dry-run --yes` |
|
|
337
|
+
| Local commit/tag only | `genbumppush patch --no-push --yes` |
|
|
338
|
+
| Nuxt or Node package | Default `package.json` adapter |
|
|
339
|
+
| npm lockfile | Add `package-lock.json` explicitly |
|
|
340
|
+
| Fixed-version monorepo | `recursive: true` |
|
|
341
|
+
| Tauri | Explicit JSON, Cargo.toml, and Cargo.lock files |
|
|
342
|
+
| Custom VERSION file | Add only if the old version occurs once |
|
|
343
|
+
| GitHub/npm publication | Push `v*`; let workflows publish |
|
|
344
|
+
| GitLab release | Run downstream jobs on `$CI_COMMIT_TAG` |
|
|
345
|
+
| Dual-host GitHub+GitLab | Set `gitlab.remote` (and `github.remote` if needed) |
|
|
325
346
|
|
|
326
347
|
## Troubleshooting
|
|
327
348
|
|
package/dist/bin.mjs
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -117,6 +117,19 @@ type GitLabOptions = {
|
|
|
117
117
|
* @example `'group/subgroup/project'`
|
|
118
118
|
*/
|
|
119
119
|
project?: string;
|
|
120
|
+
/**
|
|
121
|
+
* Git remote that points at the GitLab project.
|
|
122
|
+
*
|
|
123
|
+
* Set this in dual-host setups where `git.remote` (for example `origin`)
|
|
124
|
+
* is GitHub and GitLab is a separate remote. When the value differs from
|
|
125
|
+
* `git.remote`, genbumppush atomically pushes the release branch and tag
|
|
126
|
+
* to this remote before calling the GitLab release API. Leave unset when
|
|
127
|
+
* the primary remote already receives the tag (same remote, or a mirror
|
|
128
|
+
* that GitLab already has).
|
|
129
|
+
*
|
|
130
|
+
* @example `'gitlab'`
|
|
131
|
+
*/
|
|
132
|
+
remote?: string;
|
|
120
133
|
/**
|
|
121
134
|
* Exact environment variable name to read the token from.
|
|
122
135
|
* When set, the usual fallback chain is skipped.
|
|
@@ -154,6 +167,17 @@ type GitHubOptions = {
|
|
|
154
167
|
* @example `'xcvzmoon/genbumppush'`
|
|
155
168
|
*/
|
|
156
169
|
repo?: string;
|
|
170
|
+
/**
|
|
171
|
+
* Git remote that points at the GitHub repository.
|
|
172
|
+
*
|
|
173
|
+
* Set this in dual-host setups where `git.remote` is not GitHub. When the
|
|
174
|
+
* value differs from `git.remote`, genbumppush atomically pushes the
|
|
175
|
+
* release branch and tag to this remote before calling the GitHub release
|
|
176
|
+
* API. Leave unset when the primary remote already receives the tag.
|
|
177
|
+
*
|
|
178
|
+
* @example `'github'`
|
|
179
|
+
*/
|
|
180
|
+
remote?: string;
|
|
157
181
|
/**
|
|
158
182
|
* Exact environment variable name to read the token from.
|
|
159
183
|
* When set, the usual fallback chain is skipped.
|
|
@@ -446,7 +470,7 @@ export declare class ReleaseError extends Error {
|
|
|
446
470
|
* 2. Verify the worktree is a clean Git repo on a branch
|
|
447
471
|
* 3. Detect (or force) a release type from Conventional Commits
|
|
448
472
|
* 4. Confirm, run `before` hooks, update version files and the changelog
|
|
449
|
-
* 5. Commit, tag, and atomically push branch + tag
|
|
473
|
+
* 5. Commit, tag, and atomically push branch + tag (plus provider remotes when set)
|
|
450
474
|
* 6. Optionally create a GitHub/GitLab release, then run `after` hooks
|
|
451
475
|
*
|
|
452
476
|
* Version-file or commit failures restore files and the index. A failed tag
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as loadReleaseConfig, n as ReleaseError, r as defineConfig, t as runRelease } from "./release-
|
|
1
|
+
import { i as loadReleaseConfig, n as ReleaseError, r as defineConfig, t as runRelease } from "./release-BdWrsEaL.mjs";
|
|
2
2
|
export { ReleaseError, defineConfig, loadReleaseConfig, runRelease };
|
|
@@ -188,6 +188,16 @@ function isGitRepository(cwd) {
|
|
|
188
188
|
if (result.error || result.status !== 0 || typeof result.stdout !== "string") return false;
|
|
189
189
|
return result.stdout.trim() === "true";
|
|
190
190
|
}
|
|
191
|
+
function remoteExists(cwd, remote) {
|
|
192
|
+
return spawnSync("git", [
|
|
193
|
+
"remote",
|
|
194
|
+
"get-url",
|
|
195
|
+
remote
|
|
196
|
+
], {
|
|
197
|
+
cwd,
|
|
198
|
+
stdio: "ignore"
|
|
199
|
+
}).status === 0;
|
|
200
|
+
}
|
|
191
201
|
function remoteTagExists(cwd, remote, tag) {
|
|
192
202
|
return git([
|
|
193
203
|
"ls-remote",
|
|
@@ -754,6 +764,23 @@ function isObject(value) {
|
|
|
754
764
|
function isString(value) {
|
|
755
765
|
return Object.prototype.toString.call(value) === "[object String]";
|
|
756
766
|
}
|
|
767
|
+
function requireRemote(cwd, remote, code, provider) {
|
|
768
|
+
if (remoteExists(cwd, remote)) return;
|
|
769
|
+
throw new ReleaseError(code, `${provider} release is configured with remote "${remote}", but that remote does not exist. Add it with: git remote add ${remote} <url>`);
|
|
770
|
+
}
|
|
771
|
+
function providerRemote(configured, primaryRemote) {
|
|
772
|
+
if (configured === void 0 || configured === primaryRemote) return void 0;
|
|
773
|
+
return configured;
|
|
774
|
+
}
|
|
775
|
+
function pushRelease(cwd, remote, branch, tag) {
|
|
776
|
+
git([
|
|
777
|
+
"push",
|
|
778
|
+
"--atomic",
|
|
779
|
+
remote,
|
|
780
|
+
`HEAD:${branch}`,
|
|
781
|
+
`refs/tags/${tag}`
|
|
782
|
+
], cwd);
|
|
783
|
+
}
|
|
757
784
|
function gitLabContext(config) {
|
|
758
785
|
if (config?.enabled !== true) throw new ReleaseError("GITLAB_RELEASE_FAILED", "Enable gitlab before creating a release.");
|
|
759
786
|
const token = resolveGitLabToken(config.tokenEnv);
|
|
@@ -857,7 +884,7 @@ function packageVersion(cwd) {
|
|
|
857
884
|
* 2. Verify the worktree is a clean Git repo on a branch
|
|
858
885
|
* 3. Detect (or force) a release type from Conventional Commits
|
|
859
886
|
* 4. Confirm, run `before` hooks, update version files and the changelog
|
|
860
|
-
* 5. Commit, tag, and atomically push branch + tag
|
|
887
|
+
* 5. Commit, tag, and atomically push branch + tag (plus provider remotes when set)
|
|
861
888
|
* 6. Optionally create a GitHub/GitLab release, then run `after` hooks
|
|
862
889
|
*
|
|
863
890
|
* Version-file or commit failures restore files and the index. A failed tag
|
|
@@ -936,7 +963,8 @@ async function runRelease(options) {
|
|
|
936
963
|
const currentVersion = packageVersion(cwd);
|
|
937
964
|
if (options.gitlabRetryTag !== void 0) {
|
|
938
965
|
const context = gitLabContext(config.gitlab);
|
|
939
|
-
const remote = config.git?.remote ?? "origin";
|
|
966
|
+
const remote = config.gitlab?.remote ?? config.git?.remote ?? "origin";
|
|
967
|
+
requireRemote(cwd, remote, "GITLAB_RELEASE_FAILED", "GitLab");
|
|
940
968
|
if (!remoteTagExists(cwd, remote, options.gitlabRetryTag)) throw new ReleaseError("GITLAB_RELEASE_FAILED", `Tag ${options.gitlabRetryTag} does not exist on ${remote}.`);
|
|
941
969
|
await publishGitLab(context, cwd, config, options.gitlabRetryTag, currentVersion);
|
|
942
970
|
return {
|
|
@@ -950,7 +978,8 @@ async function runRelease(options) {
|
|
|
950
978
|
}
|
|
951
979
|
if (options.githubRetryTag !== void 0) {
|
|
952
980
|
const context = await resolveGitHubContext(config.github, cwd);
|
|
953
|
-
const remote = config.git?.remote ?? "origin";
|
|
981
|
+
const remote = config.github?.remote ?? config.git?.remote ?? "origin";
|
|
982
|
+
requireRemote(cwd, remote, "GITHUB_RELEASE_FAILED", "GitHub");
|
|
954
983
|
if (!remoteTagExists(cwd, remote, options.githubRetryTag)) throw new ReleaseError("GITHUB_RELEASE_FAILED", `Tag ${options.githubRetryTag} does not exist on ${remote}.`);
|
|
955
984
|
await publishGitHub(context, cwd, config, options.githubRetryTag, currentVersion);
|
|
956
985
|
return {
|
|
@@ -998,14 +1027,20 @@ async function runRelease(options) {
|
|
|
998
1027
|
};
|
|
999
1028
|
}
|
|
1000
1029
|
let gitlab;
|
|
1030
|
+
let gitlabRemote;
|
|
1001
1031
|
if (config.gitlab?.enabled === true) {
|
|
1002
1032
|
if (!push) throw new ReleaseError("GITLAB_RELEASE_FAILED", "GitLab release creation requires git.push to be enabled.");
|
|
1003
1033
|
gitlab = gitLabContext(config.gitlab);
|
|
1034
|
+
gitlabRemote = providerRemote(config.gitlab.remote, config.git?.remote ?? "origin");
|
|
1035
|
+
if (gitlabRemote !== void 0) requireRemote(cwd, gitlabRemote, "GITLAB_RELEASE_FAILED", "GitLab");
|
|
1004
1036
|
}
|
|
1005
1037
|
let github;
|
|
1038
|
+
let githubRemote;
|
|
1006
1039
|
if (config.github?.enabled === true) {
|
|
1007
1040
|
if (!push) throw new ReleaseError("GITHUB_RELEASE_FAILED", "GitHub release creation requires git.push to be enabled.");
|
|
1008
1041
|
github = await resolveGitHubContext(config.github, cwd);
|
|
1042
|
+
githubRemote = providerRemote(config.github.remote, config.git?.remote ?? "origin");
|
|
1043
|
+
if (githubRemote !== void 0) requireRemote(cwd, githubRemote, "GITHUB_RELEASE_FAILED", "GitHub");
|
|
1009
1044
|
}
|
|
1010
1045
|
if (!options.yes && !await confirm(`Create a ${releaseType} release?`)) throw new ReleaseError("CANCELLED", "Release cancelled.");
|
|
1011
1046
|
const version = plannedVersion;
|
|
@@ -1053,19 +1088,21 @@ async function runRelease(options) {
|
|
|
1053
1088
|
if (config.git?.sign === true) tagArgs.push("-s");
|
|
1054
1089
|
tagArgs.push(tag, "-m", render(config.git?.tagMessage ?? "v{{version}}", version));
|
|
1055
1090
|
git(tagArgs, cwd);
|
|
1056
|
-
if (push)
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1091
|
+
if (push) {
|
|
1092
|
+
pushRelease(cwd, remote, branch, tag);
|
|
1093
|
+
const extraRemotes = [...new Set([gitlabRemote, githubRemote].filter((value) => value !== void 0))];
|
|
1094
|
+
for (const extraRemote of extraRemotes) try {
|
|
1095
|
+
pushRelease(cwd, extraRemote, branch, tag);
|
|
1096
|
+
} catch (error) {
|
|
1097
|
+
throw new ReleaseError(extraRemote === gitlabRemote ? "RELEASE_PUBLISHED_GITLAB_FAILED" : "RELEASE_PUBLISHED_GITHUB_FAILED", `Git release ${tag} was pushed to ${remote}, but push to ${extraRemote} failed. Fix that remote, then run: git push --atomic ${extraRemote} HEAD:${branch} refs/tags/${tag}`, { cause: error });
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1063
1100
|
let gitlabReleaseCreated = false;
|
|
1064
1101
|
if (gitlab !== void 0) try {
|
|
1065
1102
|
await publishGitLab(gitlab, cwd, config, tag, version);
|
|
1066
1103
|
gitlabReleaseCreated = true;
|
|
1067
1104
|
} catch (error) {
|
|
1068
|
-
throw new ReleaseError("RELEASE_PUBLISHED_GITLAB_FAILED", `Git release ${tag} was pushed, but GitLab release creation failed. Retry with: genbumppush --retry-gitlab ${tag}`, { cause: error });
|
|
1105
|
+
throw new ReleaseError("RELEASE_PUBLISHED_GITLAB_FAILED", `Git release ${tag} was pushed, but GitLab release creation failed.${config.gitlab?.remote === void 0 ? " If GitLab is a separate remote from git.remote, set gitlab.remote so the tag is pushed there first." : ""} Retry with: genbumppush --retry-gitlab ${tag}`, { cause: error });
|
|
1069
1106
|
}
|
|
1070
1107
|
let githubReleaseCreated = false;
|
|
1071
1108
|
if (github !== void 0) try {
|