@releasekit/publish 0.2.0-next.9 → 0.2.0
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/LICENSE +21 -0
- package/README.md +13 -1
- package/dist/{chunk-Y7Y6GQ6R.js → chunk-H7AKSLZP.js} +223 -96
- package/dist/cli.cjs +243 -118
- package/dist/cli.js +1 -1
- package/dist/index.cjs +237 -112
- package/dist/index.d.cts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1 -1
- package/package.json +38 -28
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Sam Maister
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -82,13 +82,21 @@ releasekit-publish --input version-output.json
|
|
|
82
82
|
### In CI (GitHub Actions)
|
|
83
83
|
|
|
84
84
|
```yaml
|
|
85
|
+
- name: Configure permissions (OIDC + git pushes)
|
|
86
|
+
# at job level:
|
|
87
|
+
# permissions:
|
|
88
|
+
# id-token: write
|
|
89
|
+
# contents: write
|
|
90
|
+
|
|
85
91
|
- name: Version
|
|
86
92
|
run: releasekit-version --json > version-output.json
|
|
87
93
|
|
|
88
94
|
- name: Publish
|
|
89
95
|
run: releasekit-publish --input version-output.json
|
|
96
|
+
# For OIDC trusted publishing: no npm token needed (recommended).
|
|
97
|
+
# For token-based publishing: set NPM_TOKEN (or NODE_AUTH_TOKEN).
|
|
90
98
|
env:
|
|
91
|
-
|
|
99
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
92
100
|
```
|
|
93
101
|
|
|
94
102
|
## Configuration
|
|
@@ -105,6 +113,10 @@ Configure via `releasekit.config.json`:
|
|
|
105
113
|
"access": "public",
|
|
106
114
|
"copyFiles": ["LICENSE"]
|
|
107
115
|
},
|
|
116
|
+
"git": {
|
|
117
|
+
"pushMethod": "auto",
|
|
118
|
+
"httpsTokenEnv": "GITHUB_TOKEN"
|
|
119
|
+
},
|
|
108
120
|
"cargo": {
|
|
109
121
|
"enabled": false,
|
|
110
122
|
"noVerify": false
|
|
@@ -23,7 +23,9 @@ function getDefaultConfig() {
|
|
|
23
23
|
push: true,
|
|
24
24
|
pushMethod: "auto",
|
|
25
25
|
remote: "origin",
|
|
26
|
-
branch: "main"
|
|
26
|
+
branch: "main",
|
|
27
|
+
httpsTokenEnv: void 0,
|
|
28
|
+
skipHooks: false
|
|
27
29
|
},
|
|
28
30
|
githubRelease: {
|
|
29
31
|
enabled: true,
|
|
@@ -71,7 +73,9 @@ function toPublishConfig(config) {
|
|
|
71
73
|
push: config.git.push ?? defaults.git.push,
|
|
72
74
|
pushMethod: config.git.pushMethod ?? defaults.git.pushMethod,
|
|
73
75
|
remote: config.git.remote ?? defaults.git.remote,
|
|
74
|
-
branch: config.git.branch ?? defaults.git.branch
|
|
76
|
+
branch: config.git.branch ?? defaults.git.branch,
|
|
77
|
+
httpsTokenEnv: config.git.httpsTokenEnv ?? defaults.git.httpsTokenEnv,
|
|
78
|
+
skipHooks: config.git.skipHooks ?? defaults.git.skipHooks
|
|
75
79
|
} : defaults.git,
|
|
76
80
|
githubRelease: {
|
|
77
81
|
enabled: config.githubRelease?.enabled ?? defaults.githubRelease.enabled,
|
|
@@ -248,8 +252,20 @@ function createPublishError(code, details) {
|
|
|
248
252
|
// src/utils/exec.ts
|
|
249
253
|
import { execFile } from "child_process";
|
|
250
254
|
import { debug, info } from "@releasekit/core";
|
|
255
|
+
function redactArg(arg) {
|
|
256
|
+
try {
|
|
257
|
+
const url = new URL(arg);
|
|
258
|
+
if (url.username || url.password) {
|
|
259
|
+
url.username = url.username ? "***" : "";
|
|
260
|
+
url.password = url.password ? "***" : "";
|
|
261
|
+
return url.toString();
|
|
262
|
+
}
|
|
263
|
+
} catch {
|
|
264
|
+
}
|
|
265
|
+
return arg;
|
|
266
|
+
}
|
|
251
267
|
async function execCommand(file, args, options = {}) {
|
|
252
|
-
const displayCommand = options.label ?? [file, ...args].join(" ");
|
|
268
|
+
const displayCommand = options.label ?? [file, ...args.map(redactArg)].join(" ");
|
|
253
269
|
if (options.dryRun) {
|
|
254
270
|
info(`[DRY RUN] Would execute: ${displayCommand}`);
|
|
255
271
|
return { stdout: "", stderr: "", exitCode: 0 };
|
|
@@ -305,7 +321,7 @@ function detectNpmAuth() {
|
|
|
305
321
|
if (process.env.ACTIONS_ID_TOKEN_REQUEST_URL) {
|
|
306
322
|
return "oidc";
|
|
307
323
|
}
|
|
308
|
-
if (process.env.NPM_TOKEN) {
|
|
324
|
+
if (process.env.NPM_TOKEN || process.env.NODE_AUTH_TOKEN) {
|
|
309
325
|
return "token";
|
|
310
326
|
}
|
|
311
327
|
return null;
|
|
@@ -560,8 +576,9 @@ function topologicalSort(crates) {
|
|
|
560
576
|
import * as path3 from "path";
|
|
561
577
|
import { info as info2, success as success2 } from "@releasekit/core";
|
|
562
578
|
async function runGitCommitStage(ctx) {
|
|
563
|
-
const { input, cliOptions, cwd } = ctx;
|
|
579
|
+
const { input, config, cliOptions, cwd } = ctx;
|
|
564
580
|
const dryRun = cliOptions.dryRun;
|
|
581
|
+
const skipHooks = config.git.skipHooks ?? false;
|
|
565
582
|
if (!input.commitMessage) {
|
|
566
583
|
info2("No commit message provided, skipping git commit");
|
|
567
584
|
return;
|
|
@@ -583,8 +600,13 @@ async function runGitCommitStage(ctx) {
|
|
|
583
600
|
`git add failed: ${error instanceof Error ? error.message : String(error)}`
|
|
584
601
|
);
|
|
585
602
|
}
|
|
603
|
+
const commitArgs = ["commit"];
|
|
604
|
+
if (skipHooks) {
|
|
605
|
+
commitArgs.push("--no-verify");
|
|
606
|
+
}
|
|
607
|
+
commitArgs.push("-m", input.commitMessage);
|
|
586
608
|
try {
|
|
587
|
-
await execCommand("git",
|
|
609
|
+
await execCommand("git", commitArgs, {
|
|
588
610
|
cwd,
|
|
589
611
|
dryRun,
|
|
590
612
|
label: `git commit -m "${input.commitMessage}"`
|
|
@@ -622,6 +644,18 @@ async function runGitCommitStage(ctx) {
|
|
|
622
644
|
|
|
623
645
|
// src/stages/git-push.ts
|
|
624
646
|
import { info as info3, success as success3 } from "@releasekit/core";
|
|
647
|
+
function toGithubAuthedUrl(remoteUrl, token) {
|
|
648
|
+
try {
|
|
649
|
+
const url = new URL(remoteUrl);
|
|
650
|
+
if (url.protocol !== "https:") return void 0;
|
|
651
|
+
if (url.host !== "github.com") return void 0;
|
|
652
|
+
url.username = "x-access-token";
|
|
653
|
+
url.password = token;
|
|
654
|
+
return url.toString();
|
|
655
|
+
} catch {
|
|
656
|
+
return void 0;
|
|
657
|
+
}
|
|
658
|
+
}
|
|
625
659
|
async function runGitPushStage(ctx) {
|
|
626
660
|
const { config, cliOptions, cwd, output } = ctx;
|
|
627
661
|
const dryRun = cliOptions.dryRun;
|
|
@@ -642,16 +676,26 @@ async function runGitPushStage(ctx) {
|
|
|
642
676
|
pushMethod = "https";
|
|
643
677
|
}
|
|
644
678
|
}
|
|
679
|
+
const httpsTokenEnv = config.git.httpsTokenEnv;
|
|
680
|
+
const httpsToken = httpsTokenEnv ? process.env[httpsTokenEnv] : void 0;
|
|
645
681
|
try {
|
|
682
|
+
let pushRemote = remote;
|
|
683
|
+
if (pushMethod === "https" && httpsToken) {
|
|
684
|
+
const remoteUrlResult = await execCommand("git", ["remote", "get-url", remote], { cwd, dryRun: false });
|
|
685
|
+
const authed = toGithubAuthedUrl(remoteUrlResult.stdout.trim(), httpsToken);
|
|
686
|
+
if (authed) {
|
|
687
|
+
pushRemote = authed;
|
|
688
|
+
}
|
|
689
|
+
}
|
|
646
690
|
if (output.git.committed) {
|
|
647
|
-
await execCommand("git", ["push",
|
|
691
|
+
await execCommand("git", ["push", pushRemote, branch], {
|
|
648
692
|
cwd,
|
|
649
693
|
dryRun,
|
|
650
694
|
label: `git push ${remote} ${branch}`
|
|
651
695
|
});
|
|
652
696
|
}
|
|
653
697
|
if (output.git.tags.length > 0) {
|
|
654
|
-
await execCommand("git", ["push",
|
|
698
|
+
await execCommand("git", ["push", pushRemote, "--tags"], {
|
|
655
699
|
cwd,
|
|
656
700
|
dryRun,
|
|
657
701
|
label: `git push ${remote} --tags`
|
|
@@ -696,7 +740,9 @@ async function runGithubReleaseStage(ctx) {
|
|
|
696
740
|
if (!firstTag) return;
|
|
697
741
|
const tagsToRelease = config.githubRelease.perPackage ? tags : [firstTag];
|
|
698
742
|
for (const tag of tagsToRelease) {
|
|
699
|
-
const
|
|
743
|
+
const MAX_TAG_LENGTH = 1e3;
|
|
744
|
+
const truncatedTag = tag.length > MAX_TAG_LENGTH ? tag.slice(0, MAX_TAG_LENGTH) : tag;
|
|
745
|
+
const versionMatch = truncatedTag.match(/(\d{1,20}\.\d{1,20}\.\d{1,20}(?:[-+.]?[a-zA-Z0-9.-]{0,100})?)$/);
|
|
700
746
|
const version = versionMatch?.[1] ?? "";
|
|
701
747
|
const isPreRel = config.githubRelease.prerelease === "auto" ? version ? isPrerelease(version) : false : config.githubRelease.prerelease;
|
|
702
748
|
const result = {
|
|
@@ -738,9 +784,77 @@ async function runGithubReleaseStage(ctx) {
|
|
|
738
784
|
}
|
|
739
785
|
|
|
740
786
|
// src/stages/npm-publish.ts
|
|
787
|
+
import * as fs6 from "fs";
|
|
788
|
+
import * as path5 from "path";
|
|
789
|
+
import { debug as debug5, info as info5, success as success5, warn as warn3 } from "@releasekit/core";
|
|
790
|
+
|
|
791
|
+
// src/utils/npm-env.ts
|
|
741
792
|
import * as fs5 from "fs";
|
|
793
|
+
import * as os from "os";
|
|
742
794
|
import * as path4 from "path";
|
|
743
|
-
import { debug as debug4
|
|
795
|
+
import { debug as debug4 } from "@releasekit/core";
|
|
796
|
+
function writeTempNpmrc(contents) {
|
|
797
|
+
const dir = fs5.mkdtempSync(path4.join(os.tmpdir(), "releasekit-npmrc-"));
|
|
798
|
+
const npmrcPath = path4.join(dir, ".npmrc");
|
|
799
|
+
fs5.writeFileSync(npmrcPath, contents, "utf-8");
|
|
800
|
+
return {
|
|
801
|
+
npmrcPath,
|
|
802
|
+
cleanup: () => {
|
|
803
|
+
try {
|
|
804
|
+
fs5.rmSync(dir, { recursive: true, force: true });
|
|
805
|
+
} catch {
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
};
|
|
809
|
+
}
|
|
810
|
+
function createNpmSubprocessIsolation(options) {
|
|
811
|
+
const { authMethod, registryUrl } = options;
|
|
812
|
+
const baseEnv = {};
|
|
813
|
+
if (!authMethod) return { env: baseEnv, cleanup: () => {
|
|
814
|
+
} };
|
|
815
|
+
const token = process.env.NPM_TOKEN ?? process.env.NODE_AUTH_TOKEN;
|
|
816
|
+
const registryHost = (() => {
|
|
817
|
+
try {
|
|
818
|
+
return new URL(registryUrl).host;
|
|
819
|
+
} catch {
|
|
820
|
+
return "registry.npmjs.org";
|
|
821
|
+
}
|
|
822
|
+
})();
|
|
823
|
+
const lines = [`registry=${registryUrl}`];
|
|
824
|
+
if (authMethod === "oidc") {
|
|
825
|
+
lines.push("always-auth=false");
|
|
826
|
+
}
|
|
827
|
+
if (authMethod === "token" && token) {
|
|
828
|
+
lines.push(`//${registryHost}/:_authToken=${token}`);
|
|
829
|
+
}
|
|
830
|
+
lines.push("");
|
|
831
|
+
const { npmrcPath, cleanup } = writeTempNpmrc(lines.join("\n"));
|
|
832
|
+
debug4(`Using isolated npm userconfig: ${npmrcPath}`);
|
|
833
|
+
const isOidc = authMethod === "oidc";
|
|
834
|
+
return {
|
|
835
|
+
env: {
|
|
836
|
+
...baseEnv,
|
|
837
|
+
// Ensure npm and tools that read npm_config_* pick up our temp file
|
|
838
|
+
NPM_CONFIG_USERCONFIG: npmrcPath,
|
|
839
|
+
npm_config_userconfig: npmrcPath,
|
|
840
|
+
// Auth-specific hardening
|
|
841
|
+
...isOidc ? {
|
|
842
|
+
// Prevent setup-node's always-auth from forcing token lookups
|
|
843
|
+
NPM_CONFIG_ALWAYS_AUTH: "false",
|
|
844
|
+
npm_config_always_auth: "false",
|
|
845
|
+
// Explicitly prevent token-based publishing from being selected implicitly
|
|
846
|
+
NODE_AUTH_TOKEN: void 0,
|
|
847
|
+
NPM_TOKEN: void 0
|
|
848
|
+
} : {
|
|
849
|
+
// Ensure CLIs that expect NODE_AUTH_TOKEN can still work
|
|
850
|
+
NODE_AUTH_TOKEN: token
|
|
851
|
+
}
|
|
852
|
+
},
|
|
853
|
+
cleanup
|
|
854
|
+
};
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
// src/stages/npm-publish.ts
|
|
744
858
|
async function runNpmPublishStage(ctx) {
|
|
745
859
|
const { input, config, cliOptions, cwd } = ctx;
|
|
746
860
|
const dryRun = cliOptions.dryRun;
|
|
@@ -753,98 +867,108 @@ async function runNpmPublishStage(ctx) {
|
|
|
753
867
|
throw createPublishError("NPM_AUTH_ERROR" /* NPM_AUTH_ERROR */, "No NPM authentication method detected");
|
|
754
868
|
}
|
|
755
869
|
const useProvenance = config.npm.provenance && authMethod === "oidc";
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
870
|
+
const npmIsolation = createNpmSubprocessIsolation({
|
|
871
|
+
authMethod,
|
|
872
|
+
registryUrl: config.npm.registry
|
|
873
|
+
});
|
|
874
|
+
try {
|
|
875
|
+
for (const update of input.updates) {
|
|
876
|
+
const result = {
|
|
877
|
+
packageName: update.packageName,
|
|
878
|
+
version: update.newVersion,
|
|
879
|
+
registry: "npm",
|
|
880
|
+
success: false,
|
|
881
|
+
skipped: false
|
|
882
|
+
};
|
|
883
|
+
const pkgJsonPath = path5.resolve(cwd, update.filePath);
|
|
884
|
+
try {
|
|
885
|
+
const pkgContent = fs6.readFileSync(pkgJsonPath, "utf-8");
|
|
886
|
+
const pkgJson = JSON.parse(pkgContent);
|
|
887
|
+
if (pkgJson.private) {
|
|
888
|
+
result.skipped = true;
|
|
889
|
+
result.success = true;
|
|
890
|
+
result.reason = "Package is private";
|
|
891
|
+
ctx.output.npm.push(result);
|
|
892
|
+
debug5(`Skipping private package: ${update.packageName}`);
|
|
893
|
+
continue;
|
|
894
|
+
}
|
|
895
|
+
} catch {
|
|
896
|
+
if (update.filePath.endsWith("Cargo.toml")) {
|
|
897
|
+
result.skipped = true;
|
|
898
|
+
result.success = true;
|
|
899
|
+
result.reason = "Not an npm package";
|
|
900
|
+
ctx.output.npm.push(result);
|
|
901
|
+
continue;
|
|
902
|
+
}
|
|
775
903
|
}
|
|
776
|
-
|
|
777
|
-
|
|
904
|
+
const { file: viewFile, args: viewArgs } = buildViewCommand(
|
|
905
|
+
ctx.packageManager,
|
|
906
|
+
update.packageName,
|
|
907
|
+
update.newVersion
|
|
908
|
+
);
|
|
909
|
+
const viewResult = await execCommandSafe(viewFile, viewArgs, {
|
|
910
|
+
cwd,
|
|
911
|
+
dryRun: false,
|
|
912
|
+
// Always check, even in dry-run
|
|
913
|
+
env: npmIsolation.env
|
|
914
|
+
});
|
|
915
|
+
if (viewResult.exitCode === 0 && viewResult.stdout.trim()) {
|
|
916
|
+
result.alreadyPublished = true;
|
|
778
917
|
result.skipped = true;
|
|
779
918
|
result.success = true;
|
|
780
|
-
result.reason = "
|
|
919
|
+
result.reason = "Already published";
|
|
781
920
|
ctx.output.npm.push(result);
|
|
921
|
+
warn3(`${update.packageName}@${update.newVersion} is already published, skipping`);
|
|
782
922
|
continue;
|
|
783
923
|
}
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
ctx.packageManager,
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
cwd,
|
|
792
|
-
dryRun: false
|
|
793
|
-
// Always check, even in dry-run
|
|
794
|
-
});
|
|
795
|
-
if (viewResult.exitCode === 0 && viewResult.stdout.trim()) {
|
|
796
|
-
result.alreadyPublished = true;
|
|
797
|
-
result.skipped = true;
|
|
798
|
-
result.success = true;
|
|
799
|
-
result.reason = "Already published";
|
|
800
|
-
ctx.output.npm.push(result);
|
|
801
|
-
warn3(`${update.packageName}@${update.newVersion} is already published, skipping`);
|
|
802
|
-
continue;
|
|
803
|
-
}
|
|
804
|
-
const distTag = getDistTag(update.newVersion, config.npm.tag);
|
|
805
|
-
const pkgDir = path4.dirname(path4.resolve(cwd, update.filePath));
|
|
806
|
-
const { file: pubFile, args: pubArgs } = buildPublishCommand(ctx.packageManager, update.packageName, pkgDir, {
|
|
807
|
-
access: config.npm.access,
|
|
808
|
-
tag: distTag,
|
|
809
|
-
provenance: useProvenance,
|
|
810
|
-
noGitChecks: true
|
|
811
|
-
});
|
|
812
|
-
try {
|
|
813
|
-
await execCommand(pubFile, pubArgs, {
|
|
814
|
-
cwd,
|
|
815
|
-
dryRun,
|
|
816
|
-
label: `npm publish ${update.packageName}@${update.newVersion}`
|
|
924
|
+
const distTag = getDistTag(update.newVersion, config.npm.tag);
|
|
925
|
+
const pkgDir = path5.dirname(path5.resolve(cwd, update.filePath));
|
|
926
|
+
const { file: pubFile, args: pubArgs } = buildPublishCommand(ctx.packageManager, update.packageName, pkgDir, {
|
|
927
|
+
access: config.npm.access,
|
|
928
|
+
tag: distTag,
|
|
929
|
+
provenance: useProvenance,
|
|
930
|
+
noGitChecks: true
|
|
817
931
|
});
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
932
|
+
try {
|
|
933
|
+
await execCommand(pubFile, pubArgs, {
|
|
934
|
+
cwd,
|
|
935
|
+
dryRun,
|
|
936
|
+
label: `npm publish ${update.packageName}@${update.newVersion}`,
|
|
937
|
+
env: npmIsolation.env
|
|
938
|
+
});
|
|
939
|
+
result.success = true;
|
|
940
|
+
if (!dryRun) {
|
|
941
|
+
success5(`Published ${update.packageName}@${update.newVersion} to npm`);
|
|
942
|
+
}
|
|
943
|
+
} catch (error) {
|
|
944
|
+
result.reason = error instanceof Error ? error.message : String(error);
|
|
945
|
+
warn3(`Failed to publish ${update.packageName}: ${result.reason}`);
|
|
821
946
|
}
|
|
822
|
-
|
|
823
|
-
result.reason = error instanceof Error ? error.message : String(error);
|
|
824
|
-
warn3(`Failed to publish ${update.packageName}: ${result.reason}`);
|
|
947
|
+
ctx.output.npm.push(result);
|
|
825
948
|
}
|
|
826
|
-
|
|
949
|
+
} finally {
|
|
950
|
+
npmIsolation.cleanup();
|
|
827
951
|
}
|
|
828
952
|
}
|
|
829
953
|
|
|
830
954
|
// src/stages/prepare.ts
|
|
831
|
-
import * as
|
|
832
|
-
import * as
|
|
833
|
-
import { debug as
|
|
955
|
+
import * as fs7 from "fs";
|
|
956
|
+
import * as path6 from "path";
|
|
957
|
+
import { debug as debug6, info as info6 } from "@releasekit/core";
|
|
834
958
|
async function runPrepareStage(ctx) {
|
|
835
959
|
const { input, config, cliOptions, cwd } = ctx;
|
|
836
960
|
if (config.npm.enabled && config.npm.copyFiles.length > 0) {
|
|
837
961
|
for (const update of input.updates) {
|
|
838
|
-
const pkgDir =
|
|
962
|
+
const pkgDir = path6.dirname(path6.resolve(cwd, update.filePath));
|
|
839
963
|
for (const file of config.npm.copyFiles) {
|
|
840
|
-
const src =
|
|
841
|
-
const dest =
|
|
842
|
-
if (!
|
|
843
|
-
|
|
964
|
+
const src = path6.resolve(cwd, file);
|
|
965
|
+
const dest = path6.join(pkgDir, file);
|
|
966
|
+
if (!fs7.existsSync(src)) {
|
|
967
|
+
debug6(`Source file not found, skipping copy: ${src}`);
|
|
844
968
|
continue;
|
|
845
969
|
}
|
|
846
|
-
if (
|
|
847
|
-
|
|
970
|
+
if (path6.resolve(path6.dirname(src)) === path6.resolve(pkgDir)) {
|
|
971
|
+
debug6(`Skipping copy of ${file} - same directory as source`);
|
|
848
972
|
continue;
|
|
849
973
|
}
|
|
850
974
|
if (cliOptions.dryRun) {
|
|
@@ -852,8 +976,8 @@ async function runPrepareStage(ctx) {
|
|
|
852
976
|
continue;
|
|
853
977
|
}
|
|
854
978
|
try {
|
|
855
|
-
|
|
856
|
-
|
|
979
|
+
fs7.copyFileSync(src, dest);
|
|
980
|
+
debug6(`Copied ${file} \u2192 ${pkgDir}`);
|
|
857
981
|
} catch (error) {
|
|
858
982
|
throw createPublishError(
|
|
859
983
|
"FILE_COPY_ERROR" /* FILE_COPY_ERROR */,
|
|
@@ -865,9 +989,9 @@ async function runPrepareStage(ctx) {
|
|
|
865
989
|
}
|
|
866
990
|
if (config.cargo.enabled) {
|
|
867
991
|
for (const update of input.updates) {
|
|
868
|
-
const pkgDir =
|
|
869
|
-
const cargoPath =
|
|
870
|
-
if (!
|
|
992
|
+
const pkgDir = path6.dirname(path6.resolve(cwd, update.filePath));
|
|
993
|
+
const cargoPath = path6.join(pkgDir, "Cargo.toml");
|
|
994
|
+
if (!fs7.existsSync(cargoPath)) {
|
|
871
995
|
continue;
|
|
872
996
|
}
|
|
873
997
|
if (cliOptions.dryRun) {
|
|
@@ -875,16 +999,16 @@ async function runPrepareStage(ctx) {
|
|
|
875
999
|
continue;
|
|
876
1000
|
}
|
|
877
1001
|
updateCargoVersion(cargoPath, update.newVersion);
|
|
878
|
-
|
|
1002
|
+
debug6(`Updated ${cargoPath} to version ${update.newVersion}`);
|
|
879
1003
|
}
|
|
880
1004
|
}
|
|
881
1005
|
}
|
|
882
1006
|
|
|
883
1007
|
// src/stages/verify.ts
|
|
884
|
-
import { debug as
|
|
1008
|
+
import { debug as debug8, info as info7, success as success6, warn as warn4 } from "@releasekit/core";
|
|
885
1009
|
|
|
886
1010
|
// src/utils/retry.ts
|
|
887
|
-
import { debug as
|
|
1011
|
+
import { debug as debug7 } from "@releasekit/core";
|
|
888
1012
|
async function withRetry(fn, options, shouldRetry) {
|
|
889
1013
|
let lastError;
|
|
890
1014
|
let delay = options.initialDelay;
|
|
@@ -897,7 +1021,7 @@ async function withRetry(fn, options, shouldRetry) {
|
|
|
897
1021
|
throw error;
|
|
898
1022
|
}
|
|
899
1023
|
if (attempt < options.maxAttempts) {
|
|
900
|
-
|
|
1024
|
+
debug7(`Attempt ${attempt}/${options.maxAttempts} failed, retrying in ${delay}ms...`);
|
|
901
1025
|
await sleep(delay);
|
|
902
1026
|
delay = Math.floor(delay * options.backoffMultiplier);
|
|
903
1027
|
}
|
|
@@ -939,7 +1063,7 @@ async function runVerifyStage(ctx) {
|
|
|
939
1063
|
if (viewResult.exitCode !== 0 || !viewResult.stdout.trim()) {
|
|
940
1064
|
throw new Error(`${pkg.packageName}@${pkg.version} not yet available on npm`);
|
|
941
1065
|
}
|
|
942
|
-
|
|
1066
|
+
debug8(`Verified ${pkg.packageName}@${pkg.version} on npm`);
|
|
943
1067
|
}, config.verify.npm);
|
|
944
1068
|
result.verified = true;
|
|
945
1069
|
success6(`Verified ${pkg.packageName}@${pkg.version} on npm`);
|
|
@@ -972,7 +1096,7 @@ async function runVerifyStage(ctx) {
|
|
|
972
1096
|
if (!response.ok) {
|
|
973
1097
|
throw new Error(`${crate.packageName}@${crate.version} not yet available on crates.io`);
|
|
974
1098
|
}
|
|
975
|
-
|
|
1099
|
+
debug8(`Verified ${crate.packageName}@${crate.version} on crates.io`);
|
|
976
1100
|
}, config.verify.cargo);
|
|
977
1101
|
result.verified = true;
|
|
978
1102
|
success6(`Verified ${crate.packageName}@${crate.version} on crates.io`);
|
|
@@ -1023,7 +1147,10 @@ async function runPipeline(input, config, options) {
|
|
|
1023
1147
|
};
|
|
1024
1148
|
try {
|
|
1025
1149
|
await runPrepareStage(ctx);
|
|
1026
|
-
if (!options.skipGit) {
|
|
1150
|
+
if (options.skipGitCommit && !options.skipGit) {
|
|
1151
|
+
ctx.output.git.committed = !!input.commitMessage;
|
|
1152
|
+
ctx.output.git.tags = [...input.tags];
|
|
1153
|
+
} else if (!options.skipGit) {
|
|
1027
1154
|
await runGitCommitStage(ctx);
|
|
1028
1155
|
}
|
|
1029
1156
|
if (!options.skipPublish) {
|
|
@@ -1052,7 +1179,7 @@ async function runPipeline(input, config, options) {
|
|
|
1052
1179
|
}
|
|
1053
1180
|
|
|
1054
1181
|
// src/stages/input.ts
|
|
1055
|
-
import * as
|
|
1182
|
+
import * as fs8 from "fs";
|
|
1056
1183
|
import { info as info8 } from "@releasekit/core";
|
|
1057
1184
|
import { z } from "zod";
|
|
1058
1185
|
var VersionChangelogEntrySchema = z.object({
|
|
@@ -1086,7 +1213,7 @@ async function parseInput(inputPath) {
|
|
|
1086
1213
|
let raw;
|
|
1087
1214
|
if (inputPath) {
|
|
1088
1215
|
try {
|
|
1089
|
-
raw =
|
|
1216
|
+
raw = fs8.readFileSync(inputPath, "utf-8");
|
|
1090
1217
|
} catch {
|
|
1091
1218
|
throw createPublishError("INPUT_PARSE_ERROR" /* INPUT_PARSE_ERROR */, `Could not read file: ${inputPath}`);
|
|
1092
1219
|
}
|