@valbuild/cli 0.138.1 → 0.138.2
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/CHANGELOG.md +11 -0
- package/cli/dist/valbuild-cli-cli.cjs.dev.js +11 -1
- package/cli/dist/valbuild-cli-cli.cjs.prod.js +11 -1
- package/cli/dist/valbuild-cli-cli.esm.js +11 -1
- package/package.json +5 -5
- package/src/publish/__fixtures__/buildPublishProbe.ts +39 -3
- package/src/publish/buildPublish.test.ts +15 -1
- package/src/publish/runPublish.ts +14 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# @valbuild/cli
|
|
2
2
|
|
|
3
|
+
## 0.138.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#763](https://github.com/valbuild/val/pull/763) [`443cdcd`](https://github.com/valbuild/val/commit/443cdcdfa8948db22a54adef2ad5e18d9f9868e9) Thanks [@freekh](https://github.com/freekh)! - `val publish` now wires the site at the project's branch, which the content service names, instead of the branch the checkout is on. The site's Val saves its edits to the branch it is wired at, so publishing a managed project from a feature branch made every Studio edit land where no publish looks, and Publish answered "nothing to publish". When the two differ, the CLI says so. With a content service that does not name the branch, the checkout's is used, as before.
|
|
8
|
+
- Updated dependencies [[`2beb226`](https://github.com/valbuild/val/commit/2beb226446c76eb71026f43e04c13943da4a1e31), [`cf3bbc8`](https://github.com/valbuild/val/commit/cf3bbc8fc89ff349aac5ab101d0b4f28164583e6), [`443cdcd`](https://github.com/valbuild/val/commit/443cdcdfa8948db22a54adef2ad5e18d9f9868e9)]:
|
|
9
|
+
- @valbuild/shared@0.138.2
|
|
10
|
+
- @valbuild/core@0.138.2
|
|
11
|
+
- @valbuild/server@0.138.2
|
|
12
|
+
- @valbuild/language-server@0.138.2
|
|
13
|
+
|
|
3
14
|
## 0.138.1
|
|
4
15
|
|
|
5
16
|
### Patch Changes
|
|
@@ -3142,6 +3142,16 @@ async function runPublish(options) {
|
|
|
3142
3142
|
if (collected === null) {
|
|
3143
3143
|
log("Asking content what to build against");
|
|
3144
3144
|
const target = await client.buildTarget();
|
|
3145
|
+
/*
|
|
3146
|
+
* Wired at the PROJECT's branch, which content names, not the
|
|
3147
|
+
* checkout's: the build's Val saves its edits to the branch it is wired
|
|
3148
|
+
* at, and a publish only ever commits the project's. Wired at a feature
|
|
3149
|
+
* branch, every Studio edit was saved where no publish looks.
|
|
3150
|
+
*/
|
|
3151
|
+
const wiredBranch = target.branch ?? git.branch;
|
|
3152
|
+
if (wiredBranch !== git.branch) {
|
|
3153
|
+
log(`warn: this checkout is on ${git.branch}; the project publishes ${wiredBranch}, ` + `so the site saves its edits to ${wiredBranch}.`);
|
|
3154
|
+
}
|
|
3145
3155
|
const build = await buildArtifacts({
|
|
3146
3156
|
root,
|
|
3147
3157
|
target,
|
|
@@ -3149,7 +3159,7 @@ async function runPublish(options) {
|
|
|
3149
3159
|
contentHost,
|
|
3150
3160
|
git: {
|
|
3151
3161
|
commit: git.commit,
|
|
3152
|
-
branch:
|
|
3162
|
+
branch: wiredBranch
|
|
3153
3163
|
},
|
|
3154
3164
|
env,
|
|
3155
3165
|
log
|
|
@@ -3142,6 +3142,16 @@ async function runPublish(options) {
|
|
|
3142
3142
|
if (collected === null) {
|
|
3143
3143
|
log("Asking content what to build against");
|
|
3144
3144
|
const target = await client.buildTarget();
|
|
3145
|
+
/*
|
|
3146
|
+
* Wired at the PROJECT's branch, which content names, not the
|
|
3147
|
+
* checkout's: the build's Val saves its edits to the branch it is wired
|
|
3148
|
+
* at, and a publish only ever commits the project's. Wired at a feature
|
|
3149
|
+
* branch, every Studio edit was saved where no publish looks.
|
|
3150
|
+
*/
|
|
3151
|
+
const wiredBranch = target.branch ?? git.branch;
|
|
3152
|
+
if (wiredBranch !== git.branch) {
|
|
3153
|
+
log(`warn: this checkout is on ${git.branch}; the project publishes ${wiredBranch}, ` + `so the site saves its edits to ${wiredBranch}.`);
|
|
3154
|
+
}
|
|
3145
3155
|
const build = await buildArtifacts({
|
|
3146
3156
|
root,
|
|
3147
3157
|
target,
|
|
@@ -3149,7 +3159,7 @@ async function runPublish(options) {
|
|
|
3149
3159
|
contentHost,
|
|
3150
3160
|
git: {
|
|
3151
3161
|
commit: git.commit,
|
|
3152
|
-
branch:
|
|
3162
|
+
branch: wiredBranch
|
|
3153
3163
|
},
|
|
3154
3164
|
env,
|
|
3155
3165
|
log
|
|
@@ -3107,6 +3107,16 @@ async function runPublish(options) {
|
|
|
3107
3107
|
if (collected === null) {
|
|
3108
3108
|
log("Asking content what to build against");
|
|
3109
3109
|
const target = await client.buildTarget();
|
|
3110
|
+
/*
|
|
3111
|
+
* Wired at the PROJECT's branch, which content names, not the
|
|
3112
|
+
* checkout's: the build's Val saves its edits to the branch it is wired
|
|
3113
|
+
* at, and a publish only ever commits the project's. Wired at a feature
|
|
3114
|
+
* branch, every Studio edit was saved where no publish looks.
|
|
3115
|
+
*/
|
|
3116
|
+
const wiredBranch = target.branch ?? git.branch;
|
|
3117
|
+
if (wiredBranch !== git.branch) {
|
|
3118
|
+
log(`warn: this checkout is on ${git.branch}; the project publishes ${wiredBranch}, ` + `so the site saves its edits to ${wiredBranch}.`);
|
|
3119
|
+
}
|
|
3110
3120
|
const build = await buildArtifacts({
|
|
3111
3121
|
root,
|
|
3112
3122
|
target,
|
|
@@ -3114,7 +3124,7 @@ async function runPublish(options) {
|
|
|
3114
3124
|
contentHost,
|
|
3115
3125
|
git: {
|
|
3116
3126
|
commit: git.commit,
|
|
3117
|
-
branch:
|
|
3127
|
+
branch: wiredBranch
|
|
3118
3128
|
},
|
|
3119
3129
|
env,
|
|
3120
3130
|
log
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@valbuild/cli",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.138.
|
|
4
|
+
"version": "0.138.2",
|
|
5
5
|
"description": "Val CLI tools",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -26,11 +26,11 @@
|
|
|
26
26
|
"picocolors": "^1.1.1",
|
|
27
27
|
"zod": "^4.4.3",
|
|
28
28
|
"zod-validation-error": "^5.0.0",
|
|
29
|
-
"@valbuild/core": "0.138.
|
|
29
|
+
"@valbuild/core": "0.138.2",
|
|
30
30
|
"@valbuild/eslint-plugin": "0.125.0",
|
|
31
|
-
"@valbuild/language-server": "0.138.
|
|
32
|
-
"@valbuild/server": "0.138.
|
|
33
|
-
"@valbuild/shared": "0.138.
|
|
31
|
+
"@valbuild/language-server": "0.138.2",
|
|
32
|
+
"@valbuild/server": "0.138.2",
|
|
33
|
+
"@valbuild/shared": "0.138.2"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"prettier": "*",
|
|
@@ -68,6 +68,9 @@ export const Route = createFileRoute("/build/")({
|
|
|
68
68
|
});
|
|
69
69
|
`,
|
|
70
70
|
"src/styles.css": `h1 { color: rebeccapurple; }\n`,
|
|
71
|
+
// A Val project, so the publish wires it -- and wires it at a branch.
|
|
72
|
+
"val.config.ts": `export const config = { project: "acme/site" };\n`,
|
|
73
|
+
"val.modules.ts": `export default { modules: [] };\n`,
|
|
71
74
|
"public/robots.txt": "User-agent: *\n",
|
|
72
75
|
};
|
|
73
76
|
|
|
@@ -98,6 +101,10 @@ type Report = {
|
|
|
98
101
|
buildRouteBuilt: boolean;
|
|
99
102
|
/** Whether the checkout was left exactly as it was found. */
|
|
100
103
|
checkoutUntouched: boolean;
|
|
104
|
+
/** The branch the stored `val.server.ts` is wired at. */
|
|
105
|
+
wiredBranch: string | null;
|
|
106
|
+
/** Whether the run warned that the checkout's branch is not the project's. */
|
|
107
|
+
warnedAboutBranch: boolean;
|
|
101
108
|
};
|
|
102
109
|
|
|
103
110
|
/** A 1x1 PNG: small enough to inline, so the page carries it as a data URI. */
|
|
@@ -139,15 +146,19 @@ function listed(root: string): string[] {
|
|
|
139
146
|
async function publishOnce(
|
|
140
147
|
root: string,
|
|
141
148
|
fake: FakeContentService,
|
|
149
|
+
branch = "main",
|
|
142
150
|
): Promise<Report> {
|
|
143
151
|
const before = listed(root);
|
|
152
|
+
const logged: string[] = [];
|
|
144
153
|
const result = await runPublish({
|
|
145
154
|
root,
|
|
146
155
|
commit: COMMIT,
|
|
147
|
-
branch
|
|
156
|
+
branch,
|
|
148
157
|
env: { VAL_PROJECT_TOKEN: TOKEN, VAL_CONTENT_URL: fake.url },
|
|
149
158
|
sleep: () => Promise.resolve(),
|
|
150
|
-
log: () =>
|
|
159
|
+
log: (line: string) => {
|
|
160
|
+
logged.push(line);
|
|
161
|
+
},
|
|
151
162
|
});
|
|
152
163
|
const declared = [...fake.declarations.values()].map((body) => {
|
|
153
164
|
const d = body as {
|
|
@@ -206,9 +217,25 @@ async function publishOnce(
|
|
|
206
217
|
(JSON.parse(source.toString("utf8")) as Record<string, string>)
|
|
207
218
|
: false),
|
|
208
219
|
checkoutUntouched: JSON.stringify(listed(root)) === JSON.stringify(before),
|
|
220
|
+
wiredBranch: source ? wiredBranchOf(source) : null,
|
|
221
|
+
warnedAboutBranch: logged.some(
|
|
222
|
+
(line) => line.startsWith("warn:") && line.includes("publishes"),
|
|
223
|
+
),
|
|
209
224
|
};
|
|
210
225
|
}
|
|
211
226
|
|
|
227
|
+
/** The branch the stored `val.server.ts` was wired at: its `BUILT_FROM`. */
|
|
228
|
+
function wiredBranchOf(source: Buffer): string | null {
|
|
229
|
+
const files = JSON.parse(source.toString("utf8")) as Record<string, string>;
|
|
230
|
+
const server = Object.entries(files).find(([key]) =>
|
|
231
|
+
key.endsWith("val.server.ts"),
|
|
232
|
+
)?.[1];
|
|
233
|
+
const match = server ? /^const BUILT_FROM = (.+);$/m.exec(server) : null;
|
|
234
|
+
if (!match?.[1] || match[1] === "null") return null;
|
|
235
|
+
const parsed = JSON.parse(match[1]) as { branch?: unknown };
|
|
236
|
+
return typeof parsed.branch === "string" ? parsed.branch : null;
|
|
237
|
+
}
|
|
238
|
+
|
|
212
239
|
(async () => {
|
|
213
240
|
const root = writeProject();
|
|
214
241
|
try {
|
|
@@ -228,7 +255,16 @@ async function publishOnce(
|
|
|
228
255
|
});
|
|
229
256
|
const held = await publishOnce(root, second).finally(() => second.close());
|
|
230
257
|
|
|
231
|
-
|
|
258
|
+
// From a checkout on a feature branch, of a project content says is on main.
|
|
259
|
+
const third = await startFakeContentService({
|
|
260
|
+
token: TOKEN,
|
|
261
|
+
buildTarget: { ...FAKE_BUILD_TARGET, branch: "main" },
|
|
262
|
+
});
|
|
263
|
+
const elsewhere = await publishOnce(root, third, "feature/x").finally(() =>
|
|
264
|
+
third.close(),
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
process.stdout.write(`${JSON.stringify({ fresh, held, elsewhere })}\n`);
|
|
232
268
|
} finally {
|
|
233
269
|
fs.rmSync(root, { recursive: true, force: true });
|
|
234
270
|
}
|
|
@@ -35,9 +35,11 @@ type Run = {
|
|
|
35
35
|
clientHasLogo: boolean;
|
|
36
36
|
buildRouteBuilt: boolean;
|
|
37
37
|
checkoutUntouched: boolean;
|
|
38
|
+
wiredBranch: string | null;
|
|
39
|
+
warnedAboutBranch: boolean;
|
|
38
40
|
};
|
|
39
41
|
|
|
40
|
-
let probe: { fresh: Run; held: Run };
|
|
42
|
+
let probe: { fresh: Run; held: Run; elsewhere: Run };
|
|
41
43
|
|
|
42
44
|
beforeAll(() => {
|
|
43
45
|
const out = execFileSync(
|
|
@@ -110,6 +112,18 @@ test("a layer content already holds is named, not sent again", () => {
|
|
|
110
112
|
expect(held.declared[0]!.buildHash).toBe(fresh.declared[0]!.buildHash);
|
|
111
113
|
});
|
|
112
114
|
|
|
115
|
+
test("a checkout on another branch is wired at the project's, and says so", () => {
|
|
116
|
+
// Content names the project's branch; the site's Val saves its edits to the
|
|
117
|
+
// branch it is wired at, so a feature branch here was a site whose every
|
|
118
|
+
// Studio edit went where no publish looks.
|
|
119
|
+
expect(probe.elsewhere.result.status).toBe("live");
|
|
120
|
+
expect(probe.elsewhere.wiredBranch).toBe("main");
|
|
121
|
+
expect(probe.elsewhere.warnedAboutBranch).toBe(true);
|
|
122
|
+
// Where they agree there is nothing to say.
|
|
123
|
+
expect(probe.fresh.wiredBranch).toBe("main");
|
|
124
|
+
expect(probe.fresh.warnedAboutBranch).toBe(false);
|
|
125
|
+
});
|
|
126
|
+
|
|
113
127
|
test("the checkout is left as it was found", () => {
|
|
114
128
|
// The route tree is generated on disk and put back; the build is written
|
|
115
129
|
// to a temporary directory, not into `.val/publish`.
|
|
@@ -172,12 +172,25 @@ export async function runPublish(
|
|
|
172
172
|
if (collected === null) {
|
|
173
173
|
log("Asking content what to build against");
|
|
174
174
|
const target = await client.buildTarget();
|
|
175
|
+
/*
|
|
176
|
+
* Wired at the PROJECT's branch, which content names, not the
|
|
177
|
+
* checkout's: the build's Val saves its edits to the branch it is wired
|
|
178
|
+
* at, and a publish only ever commits the project's. Wired at a feature
|
|
179
|
+
* branch, every Studio edit was saved where no publish looks.
|
|
180
|
+
*/
|
|
181
|
+
const wiredBranch = target.branch ?? git.branch;
|
|
182
|
+
if (wiredBranch !== git.branch) {
|
|
183
|
+
log(
|
|
184
|
+
`warn: this checkout is on ${git.branch}; the project publishes ${wiredBranch}, ` +
|
|
185
|
+
`so the site saves its edits to ${wiredBranch}.`,
|
|
186
|
+
);
|
|
187
|
+
}
|
|
175
188
|
const build = await buildArtifacts({
|
|
176
189
|
root,
|
|
177
190
|
target,
|
|
178
191
|
project: project ?? "",
|
|
179
192
|
contentHost,
|
|
180
|
-
git: { commit: git.commit, branch:
|
|
193
|
+
git: { commit: git.commit, branch: wiredBranch },
|
|
181
194
|
env,
|
|
182
195
|
log,
|
|
183
196
|
});
|