@flisk-sh/flisk-import 0.2.2 → 0.2.4
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/README.md +44 -8
- package/dist/cli.js +2 -2
- package/dist/detectors/compose.js +4 -4
- package/dist/format.js +1 -1
- package/dist/plan.js +3 -3
- package/dist/scan.js +5 -5
- package/dist/tdk.js +4 -4
- package/dist/write.js +5 -5
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,24 +1,60 @@
|
|
|
1
|
-
#
|
|
1
|
+
# flisk import
|
|
2
2
|
|
|
3
|
-
Import the services in a repo's root `docker-compose.yml` into [
|
|
3
|
+
Import the services in a repo's root `docker-compose.yml` into [Flisk](https://github.com/flisk-sh/flisk) as `service.json` files. This is the Compose first tier of flisk-sh/flisk#511.
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
flisk import . --dry-run # plan only
|
|
7
|
+
flisk import . # plan, then ask before writing
|
|
8
|
+
flisk import . --yes # write service.json files and project setup
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## What to expect
|
|
12
12
|
|
|
13
13
|
- **Reads one file:** the root `docker-compose.yml`. Not `compose.yaml`, override files, nested Compose files, Dockerfiles on their own, `package.json`, or Procfiles.
|
|
14
|
-
- **Writes:** one bring-your-own `service.json` per Compose service, plus `.tdk/project.json` if the repo is not a
|
|
14
|
+
- **Writes:** one bring-your-own `service.json` per Compose service, plus `.tdk/project.json` if the repo is not a Flisk project yet. It never edits the Compose file or overwrites a `service.json` without `--force`.
|
|
15
15
|
- **Keeps:** the build context and Dockerfile (or the image), the container port, `depends_on`, and an HTTP health path. Databases and brokers are private, with no proxy route.
|
|
16
16
|
- **Drops, and says so:** env values, volumes, `command`, `env_file` and every other untranslated key; services with `profiles`, `extends`, an out-of-tree build or a `${VAR}` image.
|
|
17
|
-
- **Does not start anything.** Put env values in `.env`, then run `
|
|
17
|
+
- **Does not start anything.** Put env values in `.env`, then run `flisk up` with Flisk core **1.3.145 or later**. The importer does not check the core version.
|
|
18
18
|
- **Exit codes:** `0` when the plan succeeds (`--dry-run`, files written, or all `service.json` files already exist), `1` when no root `docker-compose.yml` or mappable service is found, and `2` when the write prompt is declined or closed without an answer (`Nothing written.`).
|
|
19
19
|
|
|
20
|
-
See [docs/import.md](docs/import.md) for the full mapping and limits. `
|
|
20
|
+
See [docs/import.md](docs/import.md) for the full mapping and limits. `flisk import` is the core CLI command backed by this package.
|
|
21
21
|
|
|
22
22
|
```bash
|
|
23
23
|
bun install && bun run build && bun run test
|
|
24
24
|
```
|
|
25
|
+
|
|
26
|
+
## Publishing
|
|
27
|
+
|
|
28
|
+
`flisk-import` is published to npmjs.org by the workflow in
|
|
29
|
+
[`.github/workflows/publish-npm.yml`](.github/workflows/publish-npm.yml), triggered by a
|
|
30
|
+
GitHub release. It uses **npm trusted publishing (OIDC)**, so no long-lived npm token
|
|
31
|
+
lives in this repository. The package is published under two names: the unscoped
|
|
32
|
+
`flisk-import` and the scoped `@flisk-sh/flisk-import` (the same archive with the name
|
|
33
|
+
rewritten in the packed manifest).
|
|
34
|
+
|
|
35
|
+
### One-time owner setup
|
|
36
|
+
|
|
37
|
+
A trusted publisher has to exist on npm before the first OIDC publish succeeds, and it is
|
|
38
|
+
configured per package name:
|
|
39
|
+
|
|
40
|
+
1. Open the package on npmjs.com → **Settings** → **Trusted Publisher** → **GitHub Actions**
|
|
41
|
+
2. Fill in:
|
|
42
|
+
- Organization: `flisk-sh`
|
|
43
|
+
- Repository: `flisk-import`
|
|
44
|
+
- Workflow filename: `publish-npm.yml`
|
|
45
|
+
- Allowed actions: `npm publish`
|
|
46
|
+
3. Repeat for `@flisk-sh/flisk-import` once that package exists
|
|
47
|
+
|
|
48
|
+
The same thing from the command line, for either name:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
npm trust github flisk-import --file publish-npm.yml --repo flisk-sh/flisk-import --allow-publish
|
|
52
|
+
npm trust list flisk-import
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### The first version
|
|
56
|
+
|
|
57
|
+
A package's first version cannot be published through OIDC — npm has no trusted publisher
|
|
58
|
+
for a name that does not exist yet. Version 0.2.2 was therefore published once with a
|
|
59
|
+
token; every version after that publishes over OIDC from the release workflow.
|
|
60
|
+
|
package/dist/cli.js
CHANGED
|
@@ -25,7 +25,7 @@ async function confirm(message) {
|
|
|
25
25
|
}
|
|
26
26
|
const program = new Command("flisk-import")
|
|
27
27
|
.version(JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")).version)
|
|
28
|
-
.description("Import services from the root docker-compose.yml into
|
|
28
|
+
.description("Import services from the root docker-compose.yml into Flisk")
|
|
29
29
|
.argument("[dir]", "Directory containing docker-compose.yml", ".")
|
|
30
30
|
.option("--dry-run", "Print the plan and write nothing", false)
|
|
31
31
|
.option("--yes", "Write without prompting", false)
|
|
@@ -60,7 +60,7 @@ const program = new Command("flisk-import")
|
|
|
60
60
|
console.log("\nNext:");
|
|
61
61
|
if (plan.services.some((s) => s.envKeys.length))
|
|
62
62
|
console.log(` - Put the environment values these services need in ${envFile}; values in docker-compose.yml were not copied.`);
|
|
63
|
-
console.log(` - Run \`
|
|
63
|
+
console.log(` - Run \`flisk up\` with Flisk core ${MIN_CORE_VERSION} or later. The import did not start anything.`);
|
|
64
64
|
});
|
|
65
65
|
try {
|
|
66
66
|
await program.parseAsync();
|
|
@@ -21,7 +21,7 @@ const NON_HTTP_PORTS = new Set([
|
|
|
21
21
|
22, 25, 1883, 2181, 3306, 5432, 5672, 6379, 9092, 9200, 11211, 27017,
|
|
22
22
|
]);
|
|
23
23
|
/**
|
|
24
|
-
* Service keys this detector translates. Every other key is named in the report:
|
|
24
|
+
* Service keys this detector translates. Every other key is named in the report: Flisk runs a
|
|
25
25
|
* bring-your-own container without volumes, command overrides, env files and the rest.
|
|
26
26
|
* `healthcheck` only contributes an HTTP path; `environment` only contributes names.
|
|
27
27
|
*/
|
|
@@ -116,7 +116,7 @@ registerDetector({
|
|
|
116
116
|
if (raw.profiles !== undefined) {
|
|
117
117
|
skips.push({
|
|
118
118
|
...base,
|
|
119
|
-
reason: `service "${name}" has profiles ${JSON.stringify(raw.profiles)}; profiles are not enforced by
|
|
119
|
+
reason: `service "${name}" has profiles ${JSON.stringify(raw.profiles)}; profiles are not enforced by Flisk`,
|
|
120
120
|
});
|
|
121
121
|
continue;
|
|
122
122
|
}
|
|
@@ -166,7 +166,7 @@ registerDetector({
|
|
|
166
166
|
else if (ports.length > 1) {
|
|
167
167
|
skips.push({
|
|
168
168
|
...base,
|
|
169
|
-
reason: `service "${name}" publishes extra container ports (${ports.filter((port) => port !== selectedPort).join(", ")});
|
|
169
|
+
reason: `service "${name}" publishes extra container ports (${ports.filter((port) => port !== selectedPort).join(", ")}); Flisk routes only ${selectedPort}`,
|
|
170
170
|
});
|
|
171
171
|
}
|
|
172
172
|
const dependsOn = Array.isArray(raw.depends_on)
|
|
@@ -183,7 +183,7 @@ registerDetector({
|
|
|
183
183
|
if (foundHealthPath && !healthCheckPath) {
|
|
184
184
|
skips.push({
|
|
185
185
|
...base,
|
|
186
|
-
reason: `service "${name}" health path "${foundHealthPath}" has characters
|
|
186
|
+
reason: `service "${name}" health path "${foundHealthPath}" has characters Flisk does not accept (only a-z, 0-9, / and -); not used`,
|
|
187
187
|
});
|
|
188
188
|
}
|
|
189
189
|
const untranslated = Object.keys(raw).filter((key) => !TRANSLATED_KEYS.has(key));
|
package/dist/format.js
CHANGED
|
@@ -10,7 +10,7 @@ export function formatPlan(plan, writes) {
|
|
|
10
10
|
const jobs = plan.services.filter((s) => s.kind === "job").length;
|
|
11
11
|
out.push(`Found ${plan.services.length - jobs} service(s) and ${jobs} job(s) in ${plan.root}`, `Read only: ${plan.files.join(", ")}. Lines below name what was not translated.`, "");
|
|
12
12
|
if (writes.projectConfig)
|
|
13
|
-
out.push(` .tdk/project.json [create
|
|
13
|
+
out.push(` .tdk/project.json [create Flisk project]`, "");
|
|
14
14
|
for (const service of plan.services) {
|
|
15
15
|
const item = writes.items.find((i) => i.service === service);
|
|
16
16
|
out.push(` ${service.name} (${service.kind}${service.dir ? `, ${service.dir}/` : ""})`);
|
package/dist/plan.js
CHANGED
|
@@ -29,11 +29,11 @@ export function buildPlan(dir) {
|
|
|
29
29
|
const isFile = (name) => statSync(resolve(root, name), { throwIfNoEntry: false })?.isFile() ?? false;
|
|
30
30
|
if (!isFile(composePath)) {
|
|
31
31
|
const others = OTHER_COMPOSE_FILES.filter(isFile);
|
|
32
|
-
throw new ImportError(`No root docker-compose.yml found in ${root}${others.length ? ` (found ${others.join(", ")})` : ""};
|
|
32
|
+
throw new ImportError(`No root docker-compose.yml found in ${root}${others.length ? ` (found ${others.join(", ")})` : ""}; flisk import reads only that file`, others.length
|
|
33
33
|
? [
|
|
34
34
|
`Other Compose file names are not read yet. To import ${others[0]}, link it: ln -s ${others[0]} docker-compose.yml`,
|
|
35
35
|
]
|
|
36
|
-
: ["Run
|
|
36
|
+
: ["Run flisk import in the directory that holds docker-compose.yml"]);
|
|
37
37
|
}
|
|
38
38
|
for (const name of OTHER_COMPOSE_FILES.filter(isFile)) {
|
|
39
39
|
skips.push({
|
|
@@ -46,7 +46,7 @@ export function buildPlan(dir) {
|
|
|
46
46
|
skips.push({
|
|
47
47
|
file: name,
|
|
48
48
|
detector: "compose",
|
|
49
|
-
reason: `not applied; \`docker compose up\` merges it over ${COMPOSE_FILE},
|
|
49
|
+
reason: `not applied; \`docker compose up\` merges it over ${COMPOSE_FILE}, flisk import does not`,
|
|
50
50
|
});
|
|
51
51
|
}
|
|
52
52
|
for (const detector of detectors) {
|
package/dist/scan.js
CHANGED
|
@@ -7,7 +7,7 @@ export const HARD_SKIPS = new Set([
|
|
|
7
7
|
"target",
|
|
8
8
|
"dist",
|
|
9
9
|
".autogenerated",
|
|
10
|
-
// Output of `
|
|
10
|
+
// Output of `flisk project`: never a source of services.
|
|
11
11
|
".tdk",
|
|
12
12
|
"shared-platform-engineering",
|
|
13
13
|
]);
|
|
@@ -83,15 +83,15 @@ export function scanTree(root, limits = { depth: MAX_DEPTH, files: MAX_FILES })
|
|
|
83
83
|
const managed = [];
|
|
84
84
|
let depthCapped = false;
|
|
85
85
|
let fileCapped = false;
|
|
86
|
-
// In a
|
|
86
|
+
// In a Flisk project, `services/` holds manifests and generated compose files, not sources.
|
|
87
87
|
const isTdkProject = existsSync(join(root, ".tdk", "project.json"));
|
|
88
88
|
if (isTdkProject)
|
|
89
|
-
notes.push("
|
|
89
|
+
notes.push("Flisk project detected: services/ was not scanned");
|
|
90
90
|
const walk = (rel, depth, inherited) => {
|
|
91
91
|
const abs = join(root, rel);
|
|
92
92
|
const rules = [...inherited, ...readIgnoreRules(abs, rel, notes)];
|
|
93
93
|
const entries = readdirSync(abs, { withFileTypes: true }).sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
|
|
94
|
-
// A directory with a service.json is already a
|
|
94
|
+
// A directory with a service.json is already a Flisk service (possibly written by an earlier
|
|
95
95
|
// import, with a scaffolded Dockerfile): re-importing it would not be idempotent.
|
|
96
96
|
if (rel !== "" && entries.some((e) => e.isFile() && e.name === "service.json")) {
|
|
97
97
|
managed.push(rel);
|
|
@@ -127,7 +127,7 @@ export function scanTree(root, limits = { depth: MAX_DEPTH, files: MAX_FILES })
|
|
|
127
127
|
};
|
|
128
128
|
walk("", 0, []);
|
|
129
129
|
if (managed.length) {
|
|
130
|
-
notes.push(`${managed.length} director${managed.length === 1 ? "y" : "ies"} with a service.json skipped (already
|
|
130
|
+
notes.push(`${managed.length} director${managed.length === 1 ? "y" : "ies"} with a service.json skipped (already Flisk services)`);
|
|
131
131
|
}
|
|
132
132
|
if (depthCapped)
|
|
133
133
|
notes.push(`directories deeper than ${limits.depth} levels were not scanned`);
|
package/dist/tdk.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
import { dirname, join, resolve } from "node:path";
|
|
3
|
-
/** Manifest constants of the
|
|
3
|
+
/** Manifest constants of the Flisk service.json this tool writes. */
|
|
4
4
|
export const SERVICE_MANIFEST_SCHEMA_VERSION = 1;
|
|
5
5
|
export const SERVICE_MANIFEST_SCHEMA_URL = "https://flisk.sh/schema.service.json";
|
|
6
6
|
/**
|
|
7
|
-
* Oldest
|
|
7
|
+
* Oldest Flisk core that starts an imported project: 1.3.104 added `buildContext`, and 1.3.145
|
|
8
8
|
* (flisk#1018) bootstraps a project that has `.tdk/project.json` but no Tiltfile yet.
|
|
9
9
|
* Stated, not checked: the importer does not read the installed core version.
|
|
10
10
|
*/
|
|
11
11
|
export const MIN_CORE_VERSION = "1.3.145";
|
|
12
|
-
/**
|
|
12
|
+
/** Flisk's bring-your-own port range. */
|
|
13
13
|
export const BYO_PORT_RANGE = { min: 4000, max: 5999, label: "4000-5999" };
|
|
14
14
|
/**
|
|
15
|
-
* Values
|
|
15
|
+
* Values Flisk copies into generated Compose and Traefik config must match these, or `flisk up` refuses
|
|
16
16
|
* the manifest (flisk `cli/src/utils/service-manifest.ts`, engine `manifest/parser.star`).
|
|
17
17
|
*/
|
|
18
18
|
export const HEALTH_CHECK_PATH_PATTERN = /^\/[a-z0-9/-]*$/;
|
package/dist/write.js
CHANGED
|
@@ -14,7 +14,7 @@ function existingPort(path) {
|
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
|
-
* Maps merged services onto
|
|
17
|
+
* Maps merged services onto Flisk bring-your-own manifests. This is the only stage that knows the
|
|
18
18
|
* layout `<project>/services/<stack>/<name>/service.json`. Nothing is written here.
|
|
19
19
|
*/
|
|
20
20
|
/** Images that serve a protocol other than HTTP. Matched against the image name, not its tag. */
|
|
@@ -40,7 +40,7 @@ export function planWrites(plan, force) {
|
|
|
40
40
|
phases: {
|
|
41
41
|
pre_alpha: {
|
|
42
42
|
name: "Pre-Alpha",
|
|
43
|
-
description: "
|
|
43
|
+
description: "Flisk proxy and imported Compose services",
|
|
44
44
|
enabledStacks: ["proxy", stack],
|
|
45
45
|
},
|
|
46
46
|
alpha: { name: "Alpha", description: "", enabledStacks: [] },
|
|
@@ -71,7 +71,7 @@ export function planWrites(plan, force) {
|
|
|
71
71
|
: !service.image
|
|
72
72
|
? "Compose gives it neither `image` nor a usable `build`"
|
|
73
73
|
: !IMAGE_PATTERN.test(service.image)
|
|
74
|
-
? `image "${service.image}" uses Compose variables or characters
|
|
74
|
+
? `image "${service.image}" uses Compose variables or characters Flisk does not accept; set a literal image in docker-compose.yml, or write this service.json by hand`
|
|
75
75
|
: undefined;
|
|
76
76
|
if (reason)
|
|
77
77
|
rejected.push({ name: service.name, reason });
|
|
@@ -138,9 +138,9 @@ export function planWrites(plan, force) {
|
|
|
138
138
|
if (service.envKeys.length)
|
|
139
139
|
notes.push("environment values are not written; put them in the project .env");
|
|
140
140
|
if (service.dockerfile && service.image)
|
|
141
|
-
notes.push(`image "${service.image}" is not written: with build and image,
|
|
141
|
+
notes.push(`image "${service.image}" is not written: with build and image, Flisk builds from ${service.dockerfile} and does not pull the tag`);
|
|
142
142
|
// With both build and image, Compose builds the Dockerfile and tags the result as `image`.
|
|
143
|
-
// Omit `image` from service.json so
|
|
143
|
+
// Omit `image` from service.json so Flisk builds from the Dockerfile instead of pulling the tag.
|
|
144
144
|
const source = service.dockerfile
|
|
145
145
|
? {
|
|
146
146
|
buildContext: relative(dirname(path), resolve(plan.root, service.dir)).split("\\").join("/") || ".",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flisk-sh/flisk-import",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "Import services from a repository's root docker-compose.yml into
|
|
3
|
+
"version": "0.2.4",
|
|
4
|
+
"description": "Import services from a repository's root docker-compose.yml into Flisk service.json files.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"bin": {
|