diff --git a/actions/checks/action.yml b/actions/checks/action.yml index b898b6c..1ca89e2 100644 --- a/actions/checks/action.yml +++ b/actions/checks/action.yml @@ -8,6 +8,10 @@ runs: shell: bash run: curl -fsSL https://bun.sh/install | bash && echo "$HOME/.bun/bin" >> "$GITHUB_PATH" + - name: Resolve external workspaces + shell: bash + run: bun "$GITHUB_ACTION_PATH/../../scripts/resolve-workspaces.ts" + - name: Install dependencies shell: bash run: bun install --frozen-lockfile diff --git a/actions/release/action.yml b/actions/release/action.yml index db2070a..30cb498 100644 --- a/actions/release/action.yml +++ b/actions/release/action.yml @@ -19,6 +19,10 @@ runs: shell: bash run: curl -fsSL https://bun.sh/install | bash && echo "$HOME/.bun/bin" >> "$GITHUB_PATH" + - name: Resolve external workspaces + shell: bash + run: bun "$GITHUB_ACTION_PATH/../../scripts/resolve-workspaces.ts" + - name: Install dependencies shell: bash run: bun install --frozen-lockfile diff --git a/scripts/resolve-workspaces.ts b/scripts/resolve-workspaces.ts new file mode 100644 index 0000000..bc37262 --- /dev/null +++ b/scripts/resolve-workspaces.ts @@ -0,0 +1,51 @@ +import { readFileSync, writeFileSync, existsSync, readdirSync } from "fs" +import { join } from "path" +import { execSync } from "child_process" + +const pkg = JSON.parse(readFileSync("package.json", "utf8")) +const ws: string[] = pkg.workspaces?.packages || pkg.workspaces || [] +if (!Array.isArray(ws)) process.exit(0) + +const ext = ws.filter((p) => p.startsWith("..")) +if (ext.length === 0) process.exit(0) + +// collect local workspace package names +const localNames = new Set() +for (const pattern of ws.filter((p) => !p.startsWith(".."))) { + const base = pattern.replace(/\/\*$/, "") + if (!existsSync(base)) continue + for (const dir of readdirSync(base, { withFileTypes: true })) { + if (!dir.isDirectory()) continue + const p = join(base, dir.name, "package.json") + if (existsSync(p)) localNames.add(JSON.parse(readFileSync(p, "utf8")).name) + } +} + +// remove external workspace entries +pkg.workspaces.packages = ws.filter((p) => !p.startsWith("..")) +writeFileSync("package.json", JSON.stringify(pkg, null, 2) + "\n") + +// find all workspace:* deps that are not local — those are external +const files = execSync('find . -name package.json -not -path "*/node_modules/*"') + .toString() + .trim() + .split("\n") + +const resolved: string[] = [] +for (const file of files) { + const content = readFileSync(file, "utf8") + let changed = content + const re = /"([^"]+)": "workspace:\*"/g + let m: RegExpExecArray | null + while ((m = re.exec(content)) !== null) { + if (!localNames.has(m[1])) { + changed = changed.replace(m[0], `"${m[1]}": "*"`) + resolved.push(m[1]) + } + } + if (changed !== content) writeFileSync(file, changed) +} + +if (resolved.length) { + console.log("Resolved external workspace deps:", [...new Set(resolved)].join(", ")) +} diff --git a/src/sync.ts b/src/sync.ts index 05898b6..5c9c444 100644 --- a/src/sync.ts +++ b/src/sync.ts @@ -49,11 +49,10 @@ export async function sync(targetDir: string): Promise { const targetPath = join(rcDir, relPath) const strategy = getStrategy(relPath, patterns) - // Check target directory exists + // Ensure target directory exists const targetFileDir = dirname(targetPath) if (!existsSync(targetFileDir)) { - console.log(` ${relPath}: ${yellow}warning: directory does not exist, skipping${reset}`) - continue + require("fs").mkdirSync(targetFileDir, { recursive: true }) } if (strategy === "merge json") {