create-windy 0.3.9 → 0.3.11
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/dist/cli.js +186 -72
- package/package.json +1 -1
- package/template/.windy-template.json +2 -2
- package/template/apps/server/Dockerfile +4 -2
- package/template/package.json +2 -0
package/dist/cli.js
CHANGED
|
@@ -835,7 +835,7 @@ var helpText = `create-windy <\u9879\u76EE\u540D> [\u9009\u9879]
|
|
|
835
835
|
|
|
836
836
|
\u9009\u9879\uFF1A
|
|
837
837
|
--profile private-enterprise \u5355\u7EC4\u7EC7\u3001\u5355\u79DF\u6237\u3001\u79C1\u6709\u90E8\u7F72 profile
|
|
838
|
-
--skip-install \
|
|
838
|
+
--skip-install \u751F\u6210\u6216\u66F4\u65B0\u65F6\u4E0D\u6267\u884C bun install
|
|
839
839
|
--verify \u5B89\u88C5\u540E\u6267\u884C lint\uFF08\u82E5\u6709\uFF09\u3001typecheck\u3001test \u548C build
|
|
840
840
|
--keep-on-error \u5931\u8D25\u65F6\u4FDD\u7559\u65B0\u751F\u6210\u76EE\u5F55\u7528\u4E8E\u8BCA\u65AD
|
|
841
841
|
--module <key> \u589E\u52A0\u6A21\u5757\uFF0C\u53EF\u91CD\u590D\u4F7F\u7528
|
|
@@ -866,7 +866,7 @@ async function runCommand(command, args, cwd) {
|
|
|
866
866
|
await new Promise((resolve2, reject) => {
|
|
867
867
|
const child = spawn(command, args, { cwd, stdio: "inherit" });
|
|
868
868
|
child.once("error", reject);
|
|
869
|
-
child.once("
|
|
869
|
+
child.once("close", (code, signal) => {
|
|
870
870
|
if (code === 0)
|
|
871
871
|
resolve2();
|
|
872
872
|
else
|
|
@@ -2851,8 +2851,22 @@ function isMissing(error) {
|
|
|
2851
2851
|
// src/docker-copy-sync.ts
|
|
2852
2852
|
var webDockerfilePath = "apps/web/Dockerfile";
|
|
2853
2853
|
var webEntryDirectory = "apps/web";
|
|
2854
|
+
var serverDockerfilePath = "apps/server/Dockerfile";
|
|
2855
|
+
var serverEntryDirectory = "apps/server";
|
|
2854
2856
|
var depsCopyAnchor = "windy-copy:deps";
|
|
2855
2857
|
var buildCopyAnchor = "windy-copy:build";
|
|
2858
|
+
var dockerfileCopyTargets = [
|
|
2859
|
+
{
|
|
2860
|
+
dockerfilePath: serverDockerfilePath,
|
|
2861
|
+
entryDirectory: serverEntryDirectory,
|
|
2862
|
+
includeBuildClosure: false
|
|
2863
|
+
},
|
|
2864
|
+
{
|
|
2865
|
+
dockerfilePath: webDockerfilePath,
|
|
2866
|
+
entryDirectory: webEntryDirectory,
|
|
2867
|
+
includeBuildClosure: true
|
|
2868
|
+
}
|
|
2869
|
+
];
|
|
2856
2870
|
async function snapshotWorkspacePackages(root, options = {}) {
|
|
2857
2871
|
const rootContent = await readSafeOptional(root, "package.json");
|
|
2858
2872
|
if (!rootContent) {
|
|
@@ -2885,10 +2899,8 @@ async function snapshotWorkspacePackages(root, options = {}) {
|
|
|
2885
2899
|
packages.push({
|
|
2886
2900
|
name: value.name,
|
|
2887
2901
|
directory: path.slice(0, -"/package.json".length),
|
|
2888
|
-
dependencies:
|
|
2889
|
-
|
|
2890
|
-
...Object.keys(value.devDependencies ?? {})
|
|
2891
|
-
]
|
|
2902
|
+
dependencies: dependencyNames(value),
|
|
2903
|
+
workspaceDependencies: workspaceDependencyNames(value)
|
|
2892
2904
|
});
|
|
2893
2905
|
}
|
|
2894
2906
|
}
|
|
@@ -2911,6 +2923,9 @@ function workspaceDependencyClosure(packages, entryDirectory) {
|
|
|
2911
2923
|
directoryByName.set(pkg.name, pkg.directory);
|
|
2912
2924
|
packageByDirectory.set(pkg.directory, pkg);
|
|
2913
2925
|
}
|
|
2926
|
+
if (!packageByDirectory.has(entryDirectory)) {
|
|
2927
|
+
throw new Error(`Docker \u5165\u53E3\u4E0D\u662F root workspace: ${entryDirectory}`);
|
|
2928
|
+
}
|
|
2914
2929
|
const visited = new Set([entryDirectory]);
|
|
2915
2930
|
const queue = [entryDirectory];
|
|
2916
2931
|
while (queue.length) {
|
|
@@ -2924,6 +2939,11 @@ function workspaceDependencyClosure(packages, entryDirectory) {
|
|
|
2924
2939
|
queue.push(directory);
|
|
2925
2940
|
}
|
|
2926
2941
|
}
|
|
2942
|
+
for (const dependency of current.workspaceDependencies ?? []) {
|
|
2943
|
+
if (!directoryByName.has(dependency)) {
|
|
2944
|
+
throw new Error(`${current.directory} \u5F15\u7528\u672A\u77E5\u6216\u8D8A\u754C workspace dependency: ${dependency}`);
|
|
2945
|
+
}
|
|
2946
|
+
}
|
|
2927
2947
|
}
|
|
2928
2948
|
return [...visited].sort((a, b) => a.localeCompare(b));
|
|
2929
2949
|
}
|
|
@@ -2940,15 +2960,16 @@ function rewriteAnchoredSection(source, anchor, lines) {
|
|
|
2940
2960
|
return [...all.slice(0, begin + 1), ...lines, ...all.slice(end)].join(`
|
|
2941
2961
|
`);
|
|
2942
2962
|
}
|
|
2943
|
-
function
|
|
2944
|
-
return source.includes(`# ${depsCopyAnchor} begin`) && source.includes(`# ${buildCopyAnchor} begin`);
|
|
2963
|
+
function hasDockerfileCopyAnchors(source, target) {
|
|
2964
|
+
return source.includes(`# ${depsCopyAnchor} begin`) && source.includes(`# ${depsCopyAnchor} end`) && (!target.includeBuildClosure || source.includes(`# ${buildCopyAnchor} begin`) && source.includes(`# ${buildCopyAnchor} end`));
|
|
2945
2965
|
}
|
|
2946
|
-
function
|
|
2947
|
-
const
|
|
2948
|
-
|
|
2966
|
+
function syncDockerfileSource(source, target, packages) {
|
|
2967
|
+
const closure = workspaceDependencyClosure(packages, target.entryDirectory);
|
|
2968
|
+
const withDeps = rewriteAnchoredSection(source, depsCopyAnchor, dockerManifestCopyLines(packages.map(({ directory }) => directory)));
|
|
2969
|
+
return target.includeBuildClosure ? rewriteAnchoredSection(withDeps, buildCopyAnchor, dockerCopyLines(closure)) : withDeps;
|
|
2949
2970
|
}
|
|
2950
|
-
async function
|
|
2951
|
-
const dockerfile = await readSafeOptional(root,
|
|
2971
|
+
async function planDockerfileInProject(root, target, options = {}) {
|
|
2972
|
+
const dockerfile = await readSafeOptional(root, target.dockerfilePath);
|
|
2952
2973
|
if (!dockerfile) {
|
|
2953
2974
|
return {
|
|
2954
2975
|
synced: false,
|
|
@@ -2958,27 +2979,27 @@ async function planWebDockerfileInProject(root, options = {}) {
|
|
|
2958
2979
|
};
|
|
2959
2980
|
}
|
|
2960
2981
|
const source = new TextDecoder().decode(dockerfile);
|
|
2961
|
-
if (!
|
|
2982
|
+
if (!hasDockerfileCopyAnchors(source, target)) {
|
|
2962
2983
|
if (!options.requireAnchors) {
|
|
2963
2984
|
return {
|
|
2964
2985
|
synced: false,
|
|
2965
2986
|
changed: false,
|
|
2966
|
-
expectations: [expectation(
|
|
2987
|
+
expectations: [expectation(target.dockerfilePath, dockerfile)],
|
|
2967
2988
|
membershipExpectations: []
|
|
2968
2989
|
};
|
|
2969
2990
|
}
|
|
2970
|
-
throw new Error(`${
|
|
2991
|
+
throw new Error(`${target.dockerfilePath} \u7F3A\u5C11\u5FC5\u9700\u7684 Docker COPY \u951A\u70B9\u6BB5\uFF0C` + `\u8BF7\u5148\u6309\u6700\u65B0\u6A21\u677F\u8FC1\u79FB\u540E\u518D\u540C\u6B65`);
|
|
2971
2992
|
}
|
|
2972
2993
|
const snapshot = await snapshotWorkspacePackages(root);
|
|
2973
2994
|
await options.afterWorkspaceSnapshot?.();
|
|
2974
2995
|
const packages = snapshot.packages;
|
|
2975
|
-
const next =
|
|
2996
|
+
const next = syncDockerfileSource(source, target, packages);
|
|
2976
2997
|
return {
|
|
2977
2998
|
synced: true,
|
|
2978
2999
|
changed: next !== source,
|
|
2979
3000
|
content: next,
|
|
2980
3001
|
expectations: [
|
|
2981
|
-
expectation(
|
|
3002
|
+
expectation(target.dockerfilePath, dockerfile),
|
|
2982
3003
|
...snapshot.expectations
|
|
2983
3004
|
],
|
|
2984
3005
|
membershipExpectations: snapshot.membershipExpectations
|
|
@@ -3002,6 +3023,18 @@ function locateAnchoredSection(source, anchor) {
|
|
|
3002
3023
|
function parseManifest(content) {
|
|
3003
3024
|
return JSON.parse(new TextDecoder().decode(content));
|
|
3004
3025
|
}
|
|
3026
|
+
function dependencyNames(manifest) {
|
|
3027
|
+
return Object.keys({
|
|
3028
|
+
...manifest.dependencies,
|
|
3029
|
+
...manifest.devDependencies
|
|
3030
|
+
});
|
|
3031
|
+
}
|
|
3032
|
+
function workspaceDependencyNames(manifest) {
|
|
3033
|
+
return Object.entries({
|
|
3034
|
+
...manifest.dependencies,
|
|
3035
|
+
...manifest.devDependencies
|
|
3036
|
+
}).filter(([, range]) => range.startsWith("workspace:")).map(([name]) => name);
|
|
3037
|
+
}
|
|
3005
3038
|
function expectation(path, content) {
|
|
3006
3039
|
return content ? { path, hash: hashContent(content) } : { path, hash: undefined };
|
|
3007
3040
|
}
|
|
@@ -3019,11 +3052,13 @@ async function prepareCustomerDockerfiles(root) {
|
|
|
3019
3052
|
const source = await readFile5(absolutePath, "utf8");
|
|
3020
3053
|
await writeFile2(absolutePath, rewriteCustomerDockerfile(source));
|
|
3021
3054
|
}));
|
|
3022
|
-
const
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3055
|
+
for (const target of dockerfileCopyTargets) {
|
|
3056
|
+
const plan = await planDockerfileInProject(root, target, {
|
|
3057
|
+
requireAnchors: true
|
|
3058
|
+
});
|
|
3059
|
+
if (plan.changed && plan.content !== undefined) {
|
|
3060
|
+
await writeFile2(join6(root, target.dockerfilePath), plan.content);
|
|
3061
|
+
}
|
|
3027
3062
|
}
|
|
3028
3063
|
}
|
|
3029
3064
|
function rewriteCustomerDockerfile(source) {
|
|
@@ -7325,6 +7360,31 @@ async function assertRestoredEntries(root, state, backups) {
|
|
|
7325
7360
|
}
|
|
7326
7361
|
}
|
|
7327
7362
|
|
|
7363
|
+
// src/update/transaction-recovery-preserves.ts
|
|
7364
|
+
async function unresolvedPreservePaths(root, backupPath, state) {
|
|
7365
|
+
const unresolved = [];
|
|
7366
|
+
for (const path2 of state.preservePaths ?? []) {
|
|
7367
|
+
const entry = state.entries.find((candidate) => candidate.path === path2);
|
|
7368
|
+
if (!entry) {
|
|
7369
|
+
unresolved.push(path2);
|
|
7370
|
+
continue;
|
|
7371
|
+
}
|
|
7372
|
+
const expected = entry.existed ? await backupExpectation(root, backupPath, entry.path, entry.mode) : { kind: "missing" };
|
|
7373
|
+
if (!matchesExpected(await hashSafePath(root, path2), await safeFileMode(root, path2), expected, entry.mode)) {
|
|
7374
|
+
unresolved.push(path2);
|
|
7375
|
+
}
|
|
7376
|
+
}
|
|
7377
|
+
return unresolved;
|
|
7378
|
+
}
|
|
7379
|
+
async function backupExpectation(root, backupPath, path2, mode) {
|
|
7380
|
+
const backupFile = `${backupPath}/files/${path2}`;
|
|
7381
|
+
const content = await readSafeOptional(root, backupFile);
|
|
7382
|
+
if (!content || mode !== undefined && await safeFileMode(root, backupFile) !== mode) {
|
|
7383
|
+
throw new Error(`\u4E8B\u52A1\u5907\u4EFD\u4E0D\u5B8C\u6574\uFF0C\u65E0\u6CD5\u89E3\u9664\u4FDD\u62A4\uFF1A${path2}`);
|
|
7384
|
+
}
|
|
7385
|
+
return { kind: "hash", value: hashContent(content) };
|
|
7386
|
+
}
|
|
7387
|
+
|
|
7328
7388
|
// src/update/transaction-recovery.ts
|
|
7329
7389
|
async function restoreUpdateState(projectDirectory, state, options) {
|
|
7330
7390
|
const root = await resolveProjectRoot(projectDirectory);
|
|
@@ -7351,8 +7411,17 @@ async function restoreUpdateState(projectDirectory, state, options) {
|
|
|
7351
7411
|
current = await retainTransactionConflicts(root, conflicts);
|
|
7352
7412
|
}
|
|
7353
7413
|
}
|
|
7414
|
+
const retainedPreservePaths = await unresolvedPreservePaths(root, backupPath, current);
|
|
7415
|
+
if (retainedPreservePaths.length !== (current.preservePaths?.length ?? 0)) {
|
|
7416
|
+
const next = {
|
|
7417
|
+
...current,
|
|
7418
|
+
preservePaths: retainedPreservePaths.length ? retainedPreservePaths : undefined
|
|
7419
|
+
};
|
|
7420
|
+
await publishTransactionState(root, current, next);
|
|
7421
|
+
current = next;
|
|
7422
|
+
}
|
|
7354
7423
|
const preserved = new Set([
|
|
7355
|
-
...
|
|
7424
|
+
...retainedPreservePaths,
|
|
7356
7425
|
...options?.preservePaths ?? []
|
|
7357
7426
|
]);
|
|
7358
7427
|
const recoveryExpectations = new Map;
|
|
@@ -7867,23 +7936,21 @@ import { readFile as readFile17 } from "fs/promises";
|
|
|
7867
7936
|
import { dirname as dirname6, join as join22 } from "path";
|
|
7868
7937
|
|
|
7869
7938
|
// src/update/docker-copy-update-plan.ts
|
|
7870
|
-
function
|
|
7871
|
-
const
|
|
7872
|
-
if (!
|
|
7873
|
-
return;
|
|
7874
|
-
const dockerSource = virtualContent(dockerPlan, snapshots);
|
|
7875
|
-
const rootPackage = virtualPathContent("package.json", files, snapshots);
|
|
7876
|
-
if (!dockerSource || !rootPackage)
|
|
7939
|
+
function deriveDockerfilePlans(files, snapshots, paths, targetWorkspaceManifests) {
|
|
7940
|
+
const rootPackage = virtualPathContent("package.json", files, snapshots, targetWorkspaceManifests);
|
|
7941
|
+
if (!rootPackage)
|
|
7877
7942
|
return;
|
|
7878
7943
|
const rootManifest = parsePackage(rootPackage, "package.json");
|
|
7879
7944
|
const workspacePatterns = rootManifest.workspaces ?? [];
|
|
7880
7945
|
const packages = [];
|
|
7881
|
-
for (const path2 of [
|
|
7946
|
+
for (const path2 of [
|
|
7947
|
+
...new Set([...paths, ...targetWorkspaceManifests.keys()])
|
|
7948
|
+
].filter((path3) => path3.endsWith("package.json"))) {
|
|
7882
7949
|
const directory = path2 === "package.json" ? "." : path2.slice(0, -13);
|
|
7883
7950
|
if (directory !== "." && !workspacePatterns.some((pattern) => matchesWorkspace(pattern, directory))) {
|
|
7884
7951
|
continue;
|
|
7885
7952
|
}
|
|
7886
|
-
const content = virtualPathContent(path2, files, snapshots);
|
|
7953
|
+
const content = virtualPathContent(path2, files, snapshots, targetWorkspaceManifests);
|
|
7887
7954
|
if (!content)
|
|
7888
7955
|
continue;
|
|
7889
7956
|
const manifest = parsePackage(content, path2);
|
|
@@ -7893,20 +7960,32 @@ function deriveWebDockerfilePlan(files, snapshots, paths) {
|
|
|
7893
7960
|
dependencies: [
|
|
7894
7961
|
...Object.keys(manifest.dependencies ?? {}),
|
|
7895
7962
|
...Object.keys(manifest.devDependencies ?? {})
|
|
7896
|
-
]
|
|
7963
|
+
],
|
|
7964
|
+
workspaceDependencies: Object.entries({
|
|
7965
|
+
...manifest.dependencies,
|
|
7966
|
+
...manifest.devDependencies
|
|
7967
|
+
}).filter(([, range]) => range.startsWith("workspace:")).map(([name]) => name)
|
|
7897
7968
|
});
|
|
7898
7969
|
}
|
|
7899
|
-
const
|
|
7900
|
-
|
|
7901
|
-
|
|
7902
|
-
|
|
7903
|
-
|
|
7904
|
-
|
|
7905
|
-
|
|
7970
|
+
for (const target of dockerfileCopyTargets) {
|
|
7971
|
+
const dockerPlan = files.find(({ path: path2 }) => path2 === target.dockerfilePath);
|
|
7972
|
+
if (!dockerPlan || dockerPlan.conflict)
|
|
7973
|
+
continue;
|
|
7974
|
+
const dockerSource = virtualContent(dockerPlan, snapshots);
|
|
7975
|
+
if (!dockerSource)
|
|
7976
|
+
continue;
|
|
7977
|
+
const source = new TextDecoder().decode(dockerSource);
|
|
7978
|
+
const next = syncDockerfileSource(source, target, packages);
|
|
7979
|
+
if (next === source)
|
|
7980
|
+
continue;
|
|
7981
|
+
dockerPlan.action = "update";
|
|
7982
|
+
dockerPlan.reason = "\u6309\u4E8B\u52A1\u5B89\u5168 workspace \u89C6\u56FE\u540C\u6B65 Docker COPY \u6E05\u5355";
|
|
7983
|
+
dockerPlan.content = new TextEncoder().encode(next);
|
|
7984
|
+
}
|
|
7906
7985
|
}
|
|
7907
|
-
function virtualPathContent(path2, files, snapshots) {
|
|
7986
|
+
function virtualPathContent(path2, files, snapshots, targetWorkspaceManifests) {
|
|
7908
7987
|
const plan = files.find((item) => item.path === path2);
|
|
7909
|
-
return plan ? virtualContent(plan, snapshots) : snapshots.get(path2);
|
|
7988
|
+
return plan ? virtualContent(plan, snapshots) : snapshots.get(path2) ?? targetWorkspaceManifests.get(path2);
|
|
7910
7989
|
}
|
|
7911
7990
|
function virtualContent(plan, snapshots) {
|
|
7912
7991
|
if (plan.action === "delete")
|
|
@@ -9014,7 +9093,9 @@ var recipes = [
|
|
|
9014
9093
|
{ id: "starter-0.3.5-to-0.3.6", from: "0.3.5", to: "0.3.6" },
|
|
9015
9094
|
{ id: "starter-0.3.6-to-0.3.7", from: "0.3.6", to: "0.3.7" },
|
|
9016
9095
|
{ id: "starter-0.3.7-to-0.3.8", from: "0.3.7", to: "0.3.8" },
|
|
9017
|
-
{ id: "starter-0.3.8-to-0.3.9", from: "0.3.8", to: "0.3.9" }
|
|
9096
|
+
{ id: "starter-0.3.8-to-0.3.9", from: "0.3.8", to: "0.3.9" },
|
|
9097
|
+
{ id: "starter-0.3.9-to-0.3.10", from: "0.3.9", to: "0.3.10" },
|
|
9098
|
+
{ id: "starter-0.3.10-to-0.3.11", from: "0.3.10", to: "0.3.11" }
|
|
9018
9099
|
];
|
|
9019
9100
|
function resolveRecipeChain(sourceVersion, targetVersion) {
|
|
9020
9101
|
if (sourceVersion === targetVersion)
|
|
@@ -9112,7 +9193,11 @@ async function createUpdatePlan(request, artifacts) {
|
|
|
9112
9193
|
manageGeneratedProjectOwned: request.targetModules !== undefined,
|
|
9113
9194
|
forcePlatformBaseline: request.forcePlatformBaseline === true
|
|
9114
9195
|
});
|
|
9115
|
-
|
|
9196
|
+
deriveDockerfilePlans(files, projectSnapshots, new Set([
|
|
9197
|
+
...paths,
|
|
9198
|
+
...workspaceSnapshot.manifests.keys(),
|
|
9199
|
+
...targetWorkspaceSnapshot.manifests.keys()
|
|
9200
|
+
]), targetWorkspaceSnapshot.manifests);
|
|
9116
9201
|
for (const file of files) {
|
|
9117
9202
|
file.expectedProjectMode = projectModes.get(file.path);
|
|
9118
9203
|
if (file.action === "create" || file.action === "update") {
|
|
@@ -10217,11 +10302,13 @@ class DefaultStarterUpdater {
|
|
|
10217
10302
|
#execute;
|
|
10218
10303
|
#beforeTransactionFinalize;
|
|
10219
10304
|
#finalizeTransaction;
|
|
10305
|
+
#skipInstall;
|
|
10220
10306
|
constructor(dependencies = {}) {
|
|
10221
10307
|
this.#artifacts = dependencies.artifacts ?? new PublishedArtifactProvider;
|
|
10222
10308
|
this.#execute = dependencies.execute ?? runCommand;
|
|
10223
10309
|
this.#beforeTransactionFinalize = dependencies.beforeTransactionFinalize;
|
|
10224
10310
|
this.#finalizeTransaction = dependencies.finalizeTransaction ?? finalizeOwnedTransaction;
|
|
10311
|
+
this.#skipInstall = dependencies.skipInstall ?? false;
|
|
10225
10312
|
}
|
|
10226
10313
|
async plan(input) {
|
|
10227
10314
|
return createUpdatePlan(input, this.#artifacts);
|
|
@@ -10241,16 +10328,34 @@ class DefaultStarterUpdater {
|
|
|
10241
10328
|
const steps = [];
|
|
10242
10329
|
let verificationExpectationsFrozen = false;
|
|
10243
10330
|
try {
|
|
10244
|
-
const dockerSync = await
|
|
10245
|
-
|
|
10246
|
-
|
|
10331
|
+
const dockerSync = await Promise.all(dockerfileCopyTargets.map((target) => planDockerfileInProject(result2.plan.projectDirectory, target, {
|
|
10332
|
+
requireAnchors: true
|
|
10333
|
+
}).then((sync) => ({ target, sync }))));
|
|
10334
|
+
const staleDockerfile = dockerSync.find(({ sync }) => sync.changed);
|
|
10335
|
+
if (staleDockerfile) {
|
|
10336
|
+
const plannedDockerfile = result2.plan.files.find(({ path: path2 }) => path2 === staleDockerfile.target.dockerfilePath);
|
|
10337
|
+
if (plannedDockerfile && plannedDockerfile.action !== "preserve" && staleDockerfile.sync.content !== undefined) {
|
|
10338
|
+
const content = new TextEncoder().encode(staleDockerfile.sync.content);
|
|
10339
|
+
await writeOwnedTransactionFile(result2.plan.projectDirectory, plannedDockerfile.path, content, expectedForPath(result2, plannedDockerfile.path));
|
|
10340
|
+
plannedDockerfile.action = "update";
|
|
10341
|
+
plannedDockerfile.content = content;
|
|
10342
|
+
replaceExpectations(result2, [
|
|
10343
|
+
expectationForContent(plannedDockerfile.path, content)
|
|
10344
|
+
]);
|
|
10345
|
+
} else {
|
|
10346
|
+
throw new TransactionCasError("Dockerfile COPY \u6E05\u5355\u672A\u5728\u66F4\u65B0\u8BA1\u5212\u4E2D\u540C\u6B65", staleDockerfile.target.dockerfilePath);
|
|
10347
|
+
}
|
|
10247
10348
|
}
|
|
10248
10349
|
steps.push({
|
|
10249
|
-
name: "\u540C\u6B65 Web Dockerfile workspace COPY \u6E05\u5355",
|
|
10250
|
-
status: dockerSync.synced ? "passed" : "skipped"
|
|
10350
|
+
name: "\u540C\u6B65 Server \u4E0E Web Dockerfile workspace COPY \u6E05\u5355",
|
|
10351
|
+
status: dockerSync.every(({ sync }) => sync.synced) ? "passed" : "skipped"
|
|
10251
10352
|
});
|
|
10252
|
-
|
|
10253
|
-
|
|
10353
|
+
if (this.#skipInstall) {
|
|
10354
|
+
steps.push({ name: "bun install --force", status: "skipped" });
|
|
10355
|
+
} else {
|
|
10356
|
+
await this.#execute("bun", ["install", "--force"], result2.plan.projectDirectory);
|
|
10357
|
+
steps.push({ name: "bun install --force", status: "passed" });
|
|
10358
|
+
}
|
|
10254
10359
|
const stabilized = await stabilizeManagedContent(result2, this.#execute, async (path2, content) => {
|
|
10255
10360
|
await writeOwnedTransactionFile(result2.plan.projectDirectory, path2, content, expectedForPath(result2, path2));
|
|
10256
10361
|
replaceExpectations(result2, [expectationForContent(path2, content)]);
|
|
@@ -10650,36 +10755,43 @@ async function runLifecycleCommand(args) {
|
|
|
10650
10755
|
return true;
|
|
10651
10756
|
}
|
|
10652
10757
|
if (command === "sync-docker") {
|
|
10653
|
-
|
|
10654
|
-
|
|
10655
|
-
|
|
10656
|
-
if (!result2.synced) {
|
|
10657
|
-
throw new Error("\u9879\u76EE\u7F3A\u5C11 apps/web/Dockerfile\uFF0C\u65E0\u6CD5\u540C\u6B65 COPY \u6E05\u5355");
|
|
10758
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
10759
|
+
console.log("\u7528\u6CD5\uFF1Acreate-windy sync-docker [--cwd <project-directory>]");
|
|
10760
|
+
return true;
|
|
10658
10761
|
}
|
|
10659
|
-
|
|
10660
|
-
|
|
10762
|
+
const plans = await Promise.all(dockerfileCopyTargets.map((target) => planDockerfileInProject(projectDirectory, target, {
|
|
10763
|
+
requireAnchors: true
|
|
10764
|
+
}).then((result2) => ({ target, result: result2 }))));
|
|
10765
|
+
if (plans.some(({ result: result2 }) => !result2.synced)) {
|
|
10766
|
+
throw new Error("\u9879\u76EE\u7F3A\u5C11\u53D7\u652F\u6301\u7684 Dockerfile\uFF0C\u65E0\u6CD5\u540C\u6B65 COPY \u6E05\u5355");
|
|
10767
|
+
}
|
|
10768
|
+
const changed = plans.filter(({ result: result2 }) => result2.changed && result2.content !== undefined);
|
|
10769
|
+
if (changed.length) {
|
|
10770
|
+
const membershipExpectations = plans.flatMap(({ result: result2 }) => result2.membershipExpectations);
|
|
10771
|
+
await assertWorkspaceMembership(projectDirectory, membershipExpectations);
|
|
10661
10772
|
const state = await applyMetadataTransaction({
|
|
10662
10773
|
id: `sync-docker-${Date.now()}`,
|
|
10663
10774
|
projectDirectory,
|
|
10664
|
-
guards: result2.expectations,
|
|
10665
|
-
writes:
|
|
10775
|
+
guards: plans.flatMap(({ result: result2 }) => result2.expectations),
|
|
10776
|
+
writes: changed.map(({ target, result: result2 }) => ({
|
|
10777
|
+
path: target.dockerfilePath,
|
|
10778
|
+
content: result2.content
|
|
10779
|
+
}))
|
|
10666
10780
|
});
|
|
10667
10781
|
await finalizeOwnedTransaction({
|
|
10668
10782
|
projectDirectory,
|
|
10669
10783
|
ownerToken: state.ownerToken,
|
|
10670
|
-
expectations:
|
|
10671
|
-
|
|
10672
|
-
|
|
10673
|
-
|
|
10674
|
-
|
|
10675
|
-
value: hashContent(result2.content)
|
|
10676
|
-
}
|
|
10784
|
+
expectations: changed.map(({ target, result: result2 }) => ({
|
|
10785
|
+
path: target.dockerfilePath,
|
|
10786
|
+
expected: {
|
|
10787
|
+
kind: "hash",
|
|
10788
|
+
value: hashContent(result2.content)
|
|
10677
10789
|
}
|
|
10678
|
-
|
|
10679
|
-
workspaceMembershipExpectations:
|
|
10790
|
+
})),
|
|
10791
|
+
workspaceMembershipExpectations: membershipExpectations
|
|
10680
10792
|
});
|
|
10681
10793
|
}
|
|
10682
|
-
console.log(
|
|
10794
|
+
console.log(changed.length ? "\u5DF2\u540C\u6B65 Server \u4E0E Web Dockerfile workspace COPY \u6E05\u5355" : "Server \u4E0E Web Dockerfile workspace COPY \u6E05\u5355\u5DF2\u662F\u6700\u65B0");
|
|
10683
10795
|
return true;
|
|
10684
10796
|
}
|
|
10685
10797
|
if (command === "doctor") {
|
|
@@ -10757,7 +10869,9 @@ async function runUpdate(args, projectDirectory) {
|
|
|
10757
10869
|
console.log(`\u9879\u76EE\u5DF2\u7ECF\u662F ${target}\uFF0C\u65E0\u9700\u66F4\u65B0`);
|
|
10758
10870
|
return;
|
|
10759
10871
|
}
|
|
10760
|
-
const updater = new DefaultStarterUpdater
|
|
10872
|
+
const updater = new DefaultStarterUpdater({
|
|
10873
|
+
skipInstall: args.includes("--skip-install")
|
|
10874
|
+
});
|
|
10761
10875
|
const plan = await updater.plan({
|
|
10762
10876
|
projectDirectory,
|
|
10763
10877
|
targetVersion: target,
|
package/package.json
CHANGED
|
@@ -4,10 +4,11 @@ FROM oven/bun:1.3.14-alpine AS deps
|
|
|
4
4
|
WORKDIR /app
|
|
5
5
|
|
|
6
6
|
COPY package.json bun.lock ./
|
|
7
|
-
|
|
8
|
-
COPY apps/web/package.json apps/web/package.json
|
|
7
|
+
# windy-copy:deps begin
|
|
9
8
|
COPY apps/license/package.json apps/license/package.json
|
|
9
|
+
COPY apps/server/package.json apps/server/package.json
|
|
10
10
|
COPY apps/signing-service/package.json apps/signing-service/package.json
|
|
11
|
+
COPY apps/web/package.json apps/web/package.json
|
|
11
12
|
COPY packages/ai-client/package.json packages/ai-client/package.json
|
|
12
13
|
COPY packages/config/package.json packages/config/package.json
|
|
13
14
|
COPY packages/create-windy/package.json packages/create-windy/package.json
|
|
@@ -20,6 +21,7 @@ COPY packages/modules/package.json packages/modules/package.json
|
|
|
20
21
|
COPY packages/server-sdk/package.json packages/server-sdk/package.json
|
|
21
22
|
COPY packages/shared/package.json packages/shared/package.json
|
|
22
23
|
COPY packages/storage/package.json packages/storage/package.json
|
|
24
|
+
# windy-copy:deps end
|
|
23
25
|
RUN bun install --frozen-lockfile
|
|
24
26
|
|
|
25
27
|
FROM deps AS runner
|
package/template/package.json
CHANGED
|
@@ -51,6 +51,8 @@
|
|
|
51
51
|
"ops:release": "bun run scripts/production-release.ts",
|
|
52
52
|
"test:merge": "bun run scripts/merge-gate.ts",
|
|
53
53
|
"release:verify": "bun run scripts/release-verify.ts",
|
|
54
|
+
"release:candidate": "bun run scripts/release-candidate.ts",
|
|
55
|
+
"release:verify:full": "bun run scripts/release-verify.ts --full",
|
|
54
56
|
"test:packages:pack": "bun run scripts/platform-package-release.ts",
|
|
55
57
|
"test:agent": "uv run --directory apps/agent-server pytest",
|
|
56
58
|
"test:document": "uv run --directory apps/document-server pytest",
|