@dbx-tools/projen 0.9.31 → 0.9.32
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/index.ts +1 -1
- package/package.json +4 -4
- package/tasks/local-publish.ts +18 -5
- package/tasks/release.ts +53 -28
package/index.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Hand edits are overwritten on the next watch; this file is read-only.
|
|
4
4
|
|
|
5
5
|
export const PACKAGE_IDENTIFIER = "@dbx-tools/projen";
|
|
6
|
-
export const PACKAGE_VERSION = "0.9.
|
|
6
|
+
export const PACKAGE_VERSION = "0.9.32";
|
|
7
7
|
export * as barrels from "./src/barrels.ts";
|
|
8
8
|
export * as bunApp from "./src/bun-app.ts";
|
|
9
9
|
export * as bunWorkflow from "./src/bun-workflow.ts";
|
package/package.json
CHANGED
|
@@ -34,9 +34,9 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@clack/prompts": "^1.7.0",
|
|
37
|
-
"@dbx-tools/core": "^0.9.
|
|
38
|
-
"@dbx-tools/path": "^0.9.
|
|
39
|
-
"@dbx-tools/shared-core": "^0.9.
|
|
37
|
+
"@dbx-tools/core": "^0.9.32",
|
|
38
|
+
"@dbx-tools/path": "^0.9.32",
|
|
39
|
+
"@dbx-tools/shared-core": "^0.9.32",
|
|
40
40
|
"commander": "^15.0.0",
|
|
41
41
|
"concurrently": "^10.0.3",
|
|
42
42
|
"constructs": "^10.6.0",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
},
|
|
57
57
|
"main": "index.ts",
|
|
58
58
|
"license": "Apache-2.0",
|
|
59
|
-
"version": "0.9.
|
|
59
|
+
"version": "0.9.32",
|
|
60
60
|
"types": "index.ts",
|
|
61
61
|
"type": "module",
|
|
62
62
|
"exports": {
|
package/tasks/local-publish.ts
CHANGED
|
@@ -28,8 +28,14 @@ export function resolveLocalRegistry(value: string): string | undefined {
|
|
|
28
28
|
return trimmed;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
/** Outcome of a local publish: which ecosystems were deployed to a local registry. */
|
|
32
|
+
export interface LocalPublishResult {
|
|
33
|
+
readonly npm: boolean;
|
|
34
|
+
readonly python: boolean;
|
|
35
|
+
}
|
|
36
|
+
|
|
31
37
|
/** Build and publish the current workspace directly to local registries. */
|
|
32
|
-
export async function publishLocalRelease(options: LocalPublishOptions): Promise<
|
|
38
|
+
export async function publishLocalRelease(options: LocalPublishOptions): Promise<LocalPublishResult> {
|
|
33
39
|
const root = resolve(options.root);
|
|
34
40
|
const localRegistry = resolveLocalRegistry(options.localRegistry);
|
|
35
41
|
const activeIndexes = activePythonIndexes();
|
|
@@ -76,8 +82,14 @@ export async function publishLocalRelease(options: LocalPublishOptions): Promise
|
|
|
76
82
|
);
|
|
77
83
|
}
|
|
78
84
|
|
|
85
|
+
if (publishes.length === 0) {
|
|
86
|
+
logger.info("no local registries configured; skipping local publish");
|
|
87
|
+
return { npm: false, python: false };
|
|
88
|
+
}
|
|
89
|
+
|
|
79
90
|
await Promise.all(publishes);
|
|
80
91
|
logger.success(`published local workspace ${options.version}`);
|
|
92
|
+
return { npm: Boolean(localRegistry), python: Boolean(localPypi) };
|
|
81
93
|
}
|
|
82
94
|
|
|
83
95
|
if (import.meta.main) {
|
|
@@ -88,20 +100,21 @@ if (import.meta.main) {
|
|
|
88
100
|
.option("--local-registry <url>", "local npm registry", "auto")
|
|
89
101
|
.option("--local-pypi <url>", "local devpi index", "auto")
|
|
90
102
|
.action(
|
|
91
|
-
(options: {
|
|
103
|
+
async (options: {
|
|
92
104
|
version: string;
|
|
93
105
|
root?: string;
|
|
94
106
|
pythonRoot: string;
|
|
95
107
|
localRegistry: string;
|
|
96
108
|
localPypi: string;
|
|
97
|
-
}) =>
|
|
98
|
-
publishLocalRelease({
|
|
109
|
+
}) => {
|
|
110
|
+
await publishLocalRelease({
|
|
99
111
|
localPypi: options.localPypi,
|
|
100
112
|
localRegistry: options.localRegistry,
|
|
101
113
|
pythonRoot: options.pythonRoot,
|
|
102
114
|
root: options.root ?? projectUtils.root() ?? process.cwd(),
|
|
103
115
|
version: options.version,
|
|
104
|
-
})
|
|
116
|
+
});
|
|
117
|
+
},
|
|
105
118
|
)
|
|
106
119
|
.parseAsync();
|
|
107
120
|
}
|
package/tasks/release.ts
CHANGED
|
@@ -10,34 +10,26 @@ import {
|
|
|
10
10
|
runTaskCommand,
|
|
11
11
|
} from "../src/_task-command.ts";
|
|
12
12
|
import { assertReleaseVersion } from "./release-version.ts";
|
|
13
|
+
import { publishLocalRelease } from "./local-publish.ts";
|
|
13
14
|
import { readWorkspaceVersion } from "../src/workspace-version.ts";
|
|
14
15
|
|
|
15
16
|
const logger = log.logger("projen:release");
|
|
16
17
|
|
|
17
|
-
export function runRelease(options: {
|
|
18
|
+
export async function runRelease(options: {
|
|
18
19
|
readonly root: string;
|
|
19
20
|
readonly branch: string;
|
|
20
21
|
readonly bump?: boolean;
|
|
21
22
|
readonly prefix: string;
|
|
22
23
|
readonly remote: string;
|
|
23
|
-
|
|
24
|
+
readonly localPublish?: boolean;
|
|
25
|
+
readonly pythonRoot?: string;
|
|
26
|
+
}): Promise<string> {
|
|
24
27
|
const { branch, prefix, remote, root } = options;
|
|
25
|
-
const currentBranch = captureGitTaskCommand(root, ["branch", "--show-current"], { check: true });
|
|
26
|
-
if (currentBranch !== branch) {
|
|
27
|
-
throw new Error(
|
|
28
|
-
`release must run on ${branch}, current branch is ${currentBranch || "detached"}`,
|
|
29
|
-
);
|
|
30
|
-
}
|
|
31
28
|
|
|
29
|
+
// Release runs from any branch: whatever is checked out is fast-forwarded onto
|
|
30
|
+
// `branch`. The working tree is committed into the release commit unless it is
|
|
31
|
+
// already clean - the clean tree is a convenience, not a precondition.
|
|
32
32
|
if (options.bump ?? true) {
|
|
33
|
-
const status = captureGitTaskCommand(
|
|
34
|
-
root,
|
|
35
|
-
["status", "--porcelain=v1", "--untracked-files=all"],
|
|
36
|
-
{ check: true },
|
|
37
|
-
);
|
|
38
|
-
if (status) {
|
|
39
|
-
throw new Error("release with automatic bump requires a clean working tree");
|
|
40
|
-
}
|
|
41
33
|
runTaskCommand(root, "bun", ["run", "bump"]);
|
|
42
34
|
}
|
|
43
35
|
|
|
@@ -64,36 +56,69 @@ export function runRelease(options: {
|
|
|
64
56
|
runGitTaskCommand(root, ["commit", "-m", `chore(release): ${version}`]);
|
|
65
57
|
}
|
|
66
58
|
|
|
59
|
+
// Fast-forward only: HEAD must already contain the remote branch tip, otherwise
|
|
60
|
+
// the push would be a non-fast-forward (an unclean merge) and we fail instead
|
|
61
|
+
// of force-pushing. This holds regardless of which branch is checked out.
|
|
67
62
|
const remoteHead = captureGitTaskCommand(root, ["rev-parse", `${remote}/${branch}`], {
|
|
68
63
|
check: true,
|
|
69
64
|
});
|
|
70
65
|
const head = captureGitTaskCommand(root, ["rev-parse", "HEAD"], { check: true });
|
|
71
66
|
if (!gitTaskCommandSucceeds(root, ["merge-base", "--is-ancestor", remoteHead, head])) {
|
|
72
|
-
throw new Error(
|
|
67
|
+
throw new Error(
|
|
68
|
+
`cannot fast-forward ${remote}/${branch} to HEAD; ${branch} has diverged (rebase before release)`,
|
|
69
|
+
);
|
|
73
70
|
}
|
|
74
71
|
|
|
75
72
|
runGitTaskCommand(root, ["push", remote, `HEAD:${branch}`]);
|
|
76
73
|
runGitTaskCommand(root, ["tag", "--annotate", tag, "--message", tag]);
|
|
77
74
|
runGitTaskCommand(root, ["push", remote, `refs/tags/${tag}`]);
|
|
78
75
|
logger.success(`released ${tag}`, { sha: head });
|
|
76
|
+
|
|
77
|
+
// Restore local deploys: when a non-standard (loopback) npm or uv registry is
|
|
78
|
+
// configured, publish the freshly tagged version to it directly. Detection and
|
|
79
|
+
// publishing are owned by local-publish.ts; this no-ops on standard registries.
|
|
80
|
+
if (options.localPublish ?? true) {
|
|
81
|
+
await publishLocalRelease({
|
|
82
|
+
localPypi: "auto",
|
|
83
|
+
localRegistry: "auto",
|
|
84
|
+
pythonRoot: options.pythonRoot ?? "packages/py",
|
|
85
|
+
root,
|
|
86
|
+
version,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
79
90
|
return tag;
|
|
80
91
|
}
|
|
81
92
|
|
|
82
93
|
if (import.meta.main) {
|
|
83
|
-
new Command()
|
|
94
|
+
await new Command()
|
|
84
95
|
.option("--root <path>", "repository root")
|
|
85
96
|
.option("--branch <name>", "release branch", "main")
|
|
86
97
|
.option("--prefix <prefix>", "release tag prefix", "v")
|
|
87
98
|
.option("--remote <name>", "git remote", "origin")
|
|
99
|
+
.option("--python-root <path>", "Python package root for local publish", "packages/py")
|
|
88
100
|
.option("--no-bump", "use an existing synchronized local version bump")
|
|
89
|
-
.
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
101
|
+
.option("--no-local-publish", "skip publishing to configured local registries")
|
|
102
|
+
.action(
|
|
103
|
+
async (options: {
|
|
104
|
+
root?: string;
|
|
105
|
+
branch: string;
|
|
106
|
+
bump: boolean;
|
|
107
|
+
prefix: string;
|
|
108
|
+
remote: string;
|
|
109
|
+
pythonRoot: string;
|
|
110
|
+
localPublish: boolean;
|
|
111
|
+
}) => {
|
|
112
|
+
await runRelease({
|
|
113
|
+
root: options.root ?? projectUtils.root() ?? process.cwd(),
|
|
114
|
+
branch: options.branch,
|
|
115
|
+
bump: options.bump,
|
|
116
|
+
prefix: options.prefix,
|
|
117
|
+
remote: options.remote,
|
|
118
|
+
pythonRoot: options.pythonRoot,
|
|
119
|
+
localPublish: options.localPublish,
|
|
120
|
+
});
|
|
121
|
+
},
|
|
122
|
+
)
|
|
123
|
+
.parseAsync();
|
|
99
124
|
}
|