mirror of
https://github.com/nocobase/nocobase.git
synced 2026-10-13 16:19:28 +08:00
docs: ship the deployment Skill with applications and finish the deployment guide (#376)
* docs: ship the deployment Skill with app-skills and close the deployment guide gaps Move `nocobase-deployment` from the repository-only `.agents/skills/` into `@nocobase/app-skills`, so `nocobase skills sync` delivers it to every generated application; the repository keeps a relative symbolic link there and the Claude mirror follows it. Point each template's AGENTS.md at the Skill, explain in the READMEs and the Skill that `pnpm build` already runs `pnpm install --prod` inside `dist/`, tell the workflow runtime's missing Artifact error how to enable the deployed hash, and fix the tutorial's archive path and start command. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * docs: write the English deployment overview, configuration, standalone and Docker pages The four pages were "Being written" placeholders while their Chinese counterparts were complete. Each now carries the same content as the Chinese page: the deployment modes and how Hub relates to applications, the shared, standalone and Hub-hosted configuration with the database, secret, address and reverse proxy details, the build-to-systemd flow with its acceptance checks, and the Docker image, Compose and update steps. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
e612b11183
commit
2ae6b2b722
@@ -11,7 +11,7 @@
|
||||
//
|
||||
// Links rather than copies, so editing a Skill through either path edits the one committed file. Relative links, so
|
||||
// the checkout stays movable.
|
||||
import { lstat, mkdir, readdir, symlink, unlink } from 'node:fs/promises';
|
||||
import { lstat, mkdir, readdir, stat, symlink, unlink } from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
import process from 'node:process';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
@@ -71,18 +71,24 @@ async function createLink(root, name, linkPath) {
|
||||
}
|
||||
}
|
||||
|
||||
// `withFileTypes` reports a symbolic link as a link rather than as the directory it points at, so `.claude/skills/`
|
||||
// has to accept both: its entries are the links this script writes, and a link whose target is already gone still has
|
||||
// to be found in order to be pruned.
|
||||
// `withFileTypes` reports a symbolic link as a link rather than as the directory it points at, so both directories
|
||||
// need care. `.claude/skills/` accepts links outright: its entries are the links this script writes, and a link whose
|
||||
// target is already gone still has to be found in order to be pruned. `.agents/skills/` accepts a link only when it
|
||||
// resolves to a directory: a Skill that is published with a package lives in that package and is committed here as a
|
||||
// relative link, and a link is still one Skill to mirror.
|
||||
async function readDirectoryNames(directory, { links = false } = {}) {
|
||||
try {
|
||||
const entries = await readdir(directory, { withFileTypes: true });
|
||||
return entries
|
||||
.filter(
|
||||
(entry) => entry.isDirectory() || (links && entry.isSymbolicLink()),
|
||||
const names = [];
|
||||
for (const entry of entries) {
|
||||
if (
|
||||
entry.isDirectory() ||
|
||||
(entry.isSymbolicLink() &&
|
||||
(links || (await isDirectory(path.join(directory, entry.name)))))
|
||||
)
|
||||
.map((entry) => entry.name)
|
||||
.sort();
|
||||
names.push(entry.name);
|
||||
}
|
||||
return names.sort();
|
||||
} catch (error) {
|
||||
if (isNodeError(error, 'ENOENT') || isNodeError(error, 'ENOTDIR'))
|
||||
return [];
|
||||
@@ -110,6 +116,16 @@ async function removeSymbolicLink(linkPath) {
|
||||
return true;
|
||||
}
|
||||
|
||||
async function isDirectory(target) {
|
||||
try {
|
||||
return (await stat(target)).isDirectory();
|
||||
} catch (error) {
|
||||
if (isNodeError(error, 'ENOENT') || isNodeError(error, 'ENOTDIR'))
|
||||
return false;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
function isNodeError(error, code) {
|
||||
return error !== null && typeof error === 'object' && error.code === code;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user