containerify 3.1.2 → 3.2.1

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 CHANGED
@@ -53,42 +53,41 @@ This will take the `nginx:alpine` image, and copy the files from `./dist/` into
53
53
  Usage: containerify [options]
54
54
 
55
55
  Options:
56
- --from <registry/image:tag> Optional: Shorthand to specify fromRegistry and fromImage in one argument
57
- --to <registry/image:tag> Optional: Shorthand to specify toRegistry and toImage in one argument
58
- --fromImage <name:tag> Required: Image name of base image - [path/]image:tag
59
- --toImage <name:tag> Required: Image name of target image - [path/]image:tag
60
- --folder <full path> Required: Base folder of node application (contains package.json)
61
- --file <path> Optional: Name of configuration file (defaults to containerify.json if found on path)
62
- --doCrossMount Optional: Cross mount image layers from the base image (only works if fromImage and toImage are in the same registry) (default: false)
63
- --fromRegistry <registry url> Optional: URL of registry to pull base image from - Default: https://registry-1.docker.io/v2/
64
- --fromToken <token> Optional: Authentication token for from registry
65
- --toRegistry <registry url> Optional: URL of registry to push base image to - Default: https://registry-1.docker.io/v2/
66
- --optimisticToRegistryCheck Treat redirects as layer existing in remote registry. Potentially unsafe, but can save bandwidth.
67
- --toToken <token> Optional: Authentication token for target registry
68
- --toTar <path> Optional: Export to tar file
69
- --toDocker Optional: Export to local docker registry
70
- --registry <path> Optional: Convenience argument for setting both from and to registry
71
- --platform <platform> Optional: Preferred platform, e.g. linux/amd64 or arm64
72
- --token <path> Optional: Convenience argument for setting token for both from and to registry
73
- --user <user> Optional: User account to run process in container - default: 1000 (empty for customContent)
74
- --workdir <directory> Optional: Workdir where node app will be added and run from - default: /app (empty for customContent)
75
- --entrypoint <entrypoint> Optional: Entrypoint when starting container - default: npm start (empty for customContent)
76
- --labels <labels> Optional: Comma-separated list of key value pairs to use as labels
77
- --label <label> Optional: Single label (name=value). This option can be used multiple times.
78
- --envs <envs> Optional: Comma-separated list of key value pairs to use av environment variables.
79
- --env <env> Optional: Single environment variable (name=value). This option can be used multiple times.
80
- --setTimeStamp <timestamp> Optional: Set a specific ISO 8601 timestamp on all entries (e.g. git commit hash). Default: 1970 in tar files, and current time on manifest/config
81
- --verbose Verbose logging
82
- --allowInsecureRegistries Allow insecure registries (with self-signed/untrusted cert)
83
- --allowNoPushAuth Allow pushing images without authentication/token if the registry allows it
84
- --customContent <dirs/files> Optional: Skip normal node_modules and applayer and include specified root folder files/directories instead. You can specify as
85
- local-path:absolute-container-path if you want to place it in a specific location
86
- --extraContent <dirs/files> Optional: Add specific content. Specify as local-path:absolute-container-path,local-path2:absolute-container-path2 etc
87
- --layerOwner <gid:uid> Optional: Set specific gid and uid on files in the added layers
88
- --buildFolder <path> Optional: Use a specific build folder when creating the image
89
- --layerCacheFolder <path> Optional: Folder to cache base layers between builds
90
- --version Get containerify version
91
- -h, --help display help for command
56
+ --from <registry/image:tag> Optional: Shorthand to specify fromRegistry and fromImage in one argument
57
+ --to <registry/image:tag> Optional: Shorthand to specify toRegistry and toImage in one argument
58
+ --fromImage <name:tag> Required: Image name of base image - [path/]image:tag
59
+ --toImage <name:tag> Required: Image name of target image - [path/]image:tag
60
+ --folder <full path> Required: Base folder of node application (contains package.json)
61
+ --file <path> Optional: Name of configuration file (defaults to containerify.json if found on path)
62
+ --doCrossMount Optional: Cross mount image layers from the base image (only works if fromImage and toImage are in the same registry) (default: false)
63
+ --fromRegistry <registry url> Optional: URL of registry to pull base image from - Default: https://registry-1.docker.io/v2/
64
+ --fromToken <token> Optional: Authentication token for from registry
65
+ --toRegistry <registry url> Optional: URL of registry to push base image to - Default: https://registry-1.docker.io/v2/
66
+ --optimisticToRegistryCheck Treat redirects as layer existing in remote registry. Potentially unsafe, but can save bandwidth.
67
+ --toToken <token> Optional: Authentication token for target registry
68
+ --toTar <path> Optional: Export to tar file
69
+ --toDocker Optional: Export to local docker registry
70
+ --registry <path> Optional: Convenience argument for setting both from and to registry
71
+ --platform <platform> Optional: Preferred platform, e.g. linux/amd64 or arm64
72
+ --token <path> Optional: Convenience argument for setting token for both from and to registry
73
+ --user <user> Optional: User account to run process in container - default: 1000 (empty for customContent)
74
+ --workdir <directory> Optional: Workdir where node app will be added and run from - default: /app (empty for customContent)
75
+ --entrypoint <entrypoint> Optional: Entrypoint when starting container - default: npm start (empty for customContent)
76
+ --label, --labels <labels...> Optional: Comma-separated list of key value pairs to use as labels
77
+ --env, --envs <envs...> Optional: Comma-separated list of key value pairs to use av environment variables.
78
+ --setTimeStamp <timestamp> Optional: Set a specific ISO 8601 timestamp on all entries (e.g. git commit hash). Default: 1970 in tar files, and current time on manifest/config
79
+ --preserveTimeStamp Optional: Preserve timestamps on files in the added layers. This might help with cache invalidation.
80
+ --verbose Verbose logging
81
+ --allowInsecureRegistries Allow insecure registries (with self-signed/untrusted cert)
82
+ --allowNoPushAuth Allow pushing images without authentication/token if the registry allows it
83
+ --customContent <dirs/files...> Optional: Skip normal node_modules and applayer and include specified root folder files/directories instead. You can specify as
84
+ local-path:absolute-container-path if you want to place it in a specific location
85
+ --extraContent <dirs/files...> Optional: Add specific content. Specify as local-path:absolute-container-path,local-path2:absolute-container-path2 etc
86
+ --layerOwner <gid:uid> Optional: Set specific gid and uid on files in the added layers
87
+ --buildFolder <path> Optional: Use a specific build folder when creating the image
88
+ --layerCacheFolder <path> Optional: Folder to cache base layers between builds
89
+ --version Get containerify version
90
+ -h, --help display help for command
92
91
  ```
93
92
 
94
93
  ## Detailed info
@@ -75,10 +75,10 @@ function calculateHash(path) {
75
75
  stream.on("end", () => resolve(hash.digest("hex")));
76
76
  });
77
77
  }
78
- function copySync(src, dest) {
79
- const copyOptions = { overwrite: true, dereference: true };
78
+ function copySync(src, dest, preserveTimestamps) {
79
+ const copyOptions = { overwrite: true, dereference: true, preserveTimestamps: preserveTimestamps };
80
80
  const destFolder = dest.substring(0, dest.lastIndexOf("/"));
81
- logger_1.default.debug("Copying " + src + " to " + dest);
81
+ logger_1.default.debug(`Copying ${src} to ${dest}`);
82
82
  fse.ensureDirSync(destFolder);
83
83
  fse.copySync(src, dest, copyOptions);
84
84
  }
@@ -112,10 +112,10 @@ function addDataLayer(tmpdir, todir, options, config, manifest, files, comment)
112
112
  const buildDir = yield fileutil.ensureEmptyDir(path.join(tmpdir, "build"));
113
113
  files.map((f) => {
114
114
  if (Array.isArray(f)) {
115
- copySync(path.join(options.folder, f[0]), path.join(buildDir, f[1]));
115
+ copySync(path.join(options.folder, f[0]), path.join(buildDir, f[1]), !!options.preserveTimeStamp);
116
116
  }
117
117
  else {
118
- copySync(path.join(options.folder, f), path.join(buildDir, options.workdir, f));
118
+ copySync(path.join(options.folder, f), path.join(buildDir, options.workdir, f), !!options.preserveTimeStamp);
119
119
  }
120
120
  });
121
121
  const layerFile = path.join(todir, "layer.tar.gz");
@@ -127,7 +127,7 @@ function addDataLayer(tmpdir, todir, options, config, manifest, files, comment)
127
127
  comment +
128
128
  (comment == "dependencies" ? ". Did you forget to run npm install?" : ""));
129
129
  }
130
- yield tar.create(Object.assign(Object.assign({}, tarDefaultConfig), Object.assign({ statCache: statCache(options.layerOwner), portable: !options.layerOwner, prefix: "/", cwd: buildDir, file: layerFile, gzip: true, noMtime: !options.setTimeStamp }, (options.setTimeStamp ? { mtime: new Date(options.setTimeStamp) } : {}))), filesToTar);
130
+ yield tar.create(Object.assign(Object.assign({}, tarDefaultConfig), Object.assign({ statCache: statCache(options.layerOwner), portable: !options.layerOwner, prefix: "/", cwd: buildDir, file: layerFile, gzip: true, noMtime: !(options.setTimeStamp || options.preserveTimeStamp) }, (options.setTimeStamp ? { mtime: new Date(options.setTimeStamp) } : {}))), filesToTar);
131
131
  const fhash = yield calculateHash(layerFile);
132
132
  const finalName = path.join(todir, fhash + ".tar.gz");
133
133
  yield fse.move(layerFile, finalName);
package/lib/cli.js CHANGED
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  step((generator = generator.apply(thisArg, _arguments || [])).next());
10
10
  });
11
11
  };
12
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
12
+ var _a, _b, _c, _d, _e, _f, _g, _h;
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
14
  const os = require("os");
15
15
  const commander_1 = require("commander");
@@ -25,67 +25,51 @@ const types_1 = require("./types");
25
25
  const utils_1 = require("./utils");
26
26
  const fileutil_1 = require("./fileutil");
27
27
  const version_1 = require("./version");
28
- const possibleArgs = {
29
- "--from <registry/image:tag>": "Optional: Shorthand to specify fromRegistry and fromImage in one argument",
30
- "--to <registry/image:tag>": "Optional: Shorthand to specify toRegistry and toImage in one argument",
31
- "--fromImage <name:tag>": "Required: Image name of base image - [path/]image:tag",
32
- "--toImage <name:tag>": "Required: Image name of target image - [path/]image:tag",
33
- "--folder <full path>": "Required: Base folder of node application (contains package.json)",
34
- "--file <path>": "Optional: Name of configuration file (defaults to containerify.json if found on path)",
35
- "--doCrossMount": "Optional: Cross mount image layers from the base image (only works if fromImage and toImage are in the same registry) (default: false)",
36
- "--fromRegistry <registry url>": "Optional: URL of registry to pull base image from - Default: https://registry-1.docker.io/v2/",
37
- "--fromToken <token>": "Optional: Authentication token for from registry",
38
- "--toRegistry <registry url>": "Optional: URL of registry to push base image to - Default: https://registry-1.docker.io/v2/",
39
- "--optimisticToRegistryCheck": "Treat redirects as layer existing in remote registry. Potentially unsafe, but can save bandwidth.",
40
- "--toToken <token>": "Optional: Authentication token for target registry",
41
- "--toTar <path>": "Optional: Export to tar file",
42
- "--toDocker": "Optional: Export to local docker registry",
43
- "--registry <path>": "Optional: Convenience argument for setting both from and to registry",
44
- "--platform <platform>": "Optional: Preferred platform, e.g. linux/amd64 or arm64",
45
- "--token <path>": "Optional: Convenience argument for setting token for both from and to registry",
46
- "--user <user>": "Optional: User account to run process in container - default: 1000 (empty for customContent)",
47
- "--workdir <directory>": "Optional: Workdir where node app will be added and run from - default: /app (empty for customContent)",
48
- "--entrypoint <entrypoint>": "Optional: Entrypoint when starting container - default: npm start (empty for customContent)",
49
- "--labels <labels>": "Optional: Comma-separated list of key value pairs to use as labels",
50
- "--label <label>": "Optional: Single label (name=value). This option can be used multiple times.",
51
- "--envs <envs>": "Optional: Comma-separated list of key value pairs to use av environment variables.",
52
- "--env <env>": "Optional: Single environment variable (name=value). This option can be used multiple times.",
53
- "--setTimeStamp <timestamp>": "Optional: Set a specific ISO 8601 timestamp on all entries (e.g. git commit hash). Default: 1970 in tar files, and current time on manifest/config",
54
- "--verbose": "Verbose logging",
55
- "--allowInsecureRegistries": "Allow insecure registries (with self-signed/untrusted cert)",
56
- "--allowNoPushAuth": "Allow pushing images without a authentication/token to registries that allow it",
57
- "--customContent <dirs/files>": "Optional: Skip normal node_modules and applayer and include specified root folder files/directories instead. You can specify as local-path:absolute-container-path if you want to place it in a specific location",
58
- "--extraContent <dirs/files>": "Optional: Add specific content. Specify as local-path:absolute-container-path,local-path2:absolute-container-path2 etc",
59
- "--layerOwner <gid:uid>": "Optional: Set specific gid and uid on files in the added layers",
60
- "--buildFolder <path>": "Optional: Use a specific build folder when creating the image",
61
- "--layerCacheFolder <path>": "Optional: Folder to cache base layers between builds",
62
- "--version": "Get containerify version",
63
- };
28
+ const program = new commander_1.Command();
29
+ program
30
+ .name("containerify")
31
+ .description("A CLI-tool for creating container images.")
32
+ .option("--from <registry/image:tag>", "Optional: Shorthand to specify fromRegistry and fromImage in one argument")
33
+ .option("--to <registry/image:tag>", "Optional: Shorthand to specify toRegistry and toImage in one argument")
34
+ .option("--fromImage <name:tag>", "Required: Image name of base image - [path/]image:tag")
35
+ .option("--toImage <name:tag>", "Required: Image name of target image - [path/]image:tag")
36
+ .option("--folder <full path>", "Required: Base folder of node application (contains package.json)")
37
+ .option("--file <path>", "Optional: Name of configuration file (defaults to containerify.json if found on path)")
38
+ .option("--doCrossMount", "Optional: Cross mount image layers from the base image (only works if fromImage and toImage are in the same registry) (default, false)")
39
+ .option("--fromRegistry <registry url>", "Optional: URL of registry to pull base image from - Default, https,//registry-1.docker.io/v2/")
40
+ .option("--fromToken <token>", "Optional: Authentication token for from registry")
41
+ .option("--toRegistry <registry url>", "Optional: URL of registry to push base image to - Default, https,//registry-1.docker.io/v2/")
42
+ .option("--optimisticToRegistryCheck", "Treat redirects as layer existing in remote registry. Potentially unsafe) but can save bandwidth.")
43
+ .option("--toToken <token>", "Optional: Authentication token for target registry")
44
+ .option("--toTar <path>", "Optional: Export to tar file")
45
+ .option("--toDocker", "Optional: Export to local docker registry")
46
+ .option("--registry <path>", "Optional: Convenience argument for setting both from and to registry")
47
+ .option("--platform <platform>", "Optional: Preferred platform) e.g. linux/amd64 or arm64")
48
+ .option("--token <path>", "Optional: Convenience argument for setting token for both from and to registry")
49
+ .option("--user <user>", "Optional: User account to run process in container - default, 1000 (empty for customContent)")
50
+ .option("--workdir <directory>", "Optional: Workdir where node app will be added and run from - default, /app (empty for customContent)")
51
+ .option("--entrypoint <entrypoint>", "Optional: Entrypoint when starting container - default, npm start (empty for customContent)")
52
+ .option("--label, --labels <labels...>", "Optional: Comma-separated list of key value pairs to use as labels")
53
+ .option("--env, --envs <envs...>", "Optional: Comma-separated list of key value pairs to use av environment variables.")
54
+ .option("--preserveTimeStamp", "Optional: Preserve timestamps on files in the added layers. This might help with cache invalidation.")
55
+ .option("--setTimeStamp <timestamp>", "Optional: Set a specific ISO 8601 timestamp on all entries (e.g. git commit hash). Default, 1970 in tar files) and current time on manifest/config")
56
+ .option("--verbose", "Verbose logging")
57
+ .option("--allowInsecureRegistries", "Allow insecure registries (with self-signed/untrusted cert)")
58
+ .option("--allowNoPushAuth", "Allow pushing images without a authentication/token to registries that allow it")
59
+ .option("--customContent <dirs/files...>", "Optional: Skip normal node_modules and applayer and include specified root folder files/directories instead. You can specify as local-path,absolute-container-path if you want to place it in a specific location")
60
+ .option("--extraContent <dirs/files...>", "Optional: Add specific content. Specify as local-path,absolute-container-path)local-path2,absolute-container-path2 etc")
61
+ .option("--layerOwner <gid:uid>", "Optional: Set specific gid and uid on files in the added layers")
62
+ .option("--buildFolder <path>", "Optional: Use a specific build folder when creating the image")
63
+ .option("--layerCacheFolder <path>", "Optional: Folder to cache base layers between builds")
64
+ .version(version_1.VERSION, "--version", "Get containerify version");
65
+ program.parse(process.argv);
64
66
  function setKeyValue(target, keyValue, separator = "=", defaultValue) {
65
67
  var _a;
66
68
  const [k, v] = keyValue.split(separator, 2);
67
69
  target[k.trim()] = (_a = v === null || v === void 0 ? void 0 : v.trim()) !== null && _a !== void 0 ? _a : defaultValue;
68
70
  }
69
- const cliLabels = {};
70
- commander_1.program.on("option:label", (ops) => {
71
- setKeyValue(cliLabels, ops);
72
- });
73
- const cliEnv = {};
74
- commander_1.program.on("option:env", (ops) => {
75
- setKeyValue(cliEnv, ops);
76
- });
77
- const cliOptions = Object.entries(possibleArgs)
78
- .reduce((program, [k, v]) => {
79
- program.option(k, v);
80
- return program;
81
- }, commander_1.program)
82
- .parse()
83
- .opts();
84
- if (cliOptions.version) {
85
- console.log(`containerify v${version_1.VERSION}`);
86
- process.exit(0);
87
- }
88
- const keys = Object.keys(possibleArgs).map((k) => k.split(" ")[0].replace("--", ""));
71
+ const cliOptions = program.opts();
72
+ const keys = program.options.map((x) => { var _a; return (_a = x.long) === null || _a === void 0 ? void 0 : _a.replace("--", ""); });
89
73
  const defaultOptions = {
90
74
  workdir: "/app",
91
75
  user: "1000",
@@ -107,26 +91,17 @@ Object.keys(configFromFile).forEach((k) => {
107
91
  }
108
92
  });
109
93
  const labelsOpt = {};
110
- (_b = (_a = cliOptions.labels) === null || _a === void 0 ? void 0 : _a.split(",")) === null || _b === void 0 ? void 0 : _b.forEach((x) => setKeyValue(labelsOpt, x));
111
- Object.keys(labelsOpt)
112
- .filter((l) => Object.keys(cliLabels).includes(l))
113
- .forEach((l) => {
114
- exitWithErrorIf(true, `Label ${l} specified both with --labels and --label`);
115
- });
116
- const labels = Object.assign(Object.assign(Object.assign({}, configFromFile.labels), labelsOpt), cliLabels); //Let cli arguments override file
94
+ (_a = cliOptions.labels) === null || _a === void 0 ? void 0 : _a.forEach((labels) => labels.split(",").forEach((label) => setKeyValue(labelsOpt, label)));
95
+ const labels = Object.assign(Object.assign({}, configFromFile.labels), labelsOpt); //Let cli arguments override file
117
96
  const envOpt = {};
118
- (_d = (_c = cliOptions.envs) === null || _c === void 0 ? void 0 : _c.split(",")) === null || _d === void 0 ? void 0 : _d.forEach((x) => setKeyValue(envOpt, x));
119
- Object.keys(envOpt)
120
- .filter((l) => Object.keys(cliEnv).includes(l))
121
- .forEach((l) => {
122
- exitWithErrorIf(true, `Env ${l} specified both with --envs and --env`);
123
- });
124
- const envs = Object.assign(Object.assign(Object.assign({}, configFromFile.envs), envOpt), cliEnv); //Let cli arguments override file
97
+ (_b = cliOptions.envs) === null || _b === void 0 ? void 0 : _b.forEach((envs) => envs.split(",").forEach((env) => setKeyValue(envOpt, env)));
98
+ const envs = Object.assign(Object.assign({}, configFromFile.envs), envOpt); //Let cli arguments override file
99
+ console.log(envs);
125
100
  const customContent = {};
126
- (_e = configFromFile.customContent) === null || _e === void 0 ? void 0 : _e.forEach((c) => setKeyValue(customContent, c, ":", c));
127
- (_f = cliOptions.customContent) === null || _f === void 0 ? void 0 : _f.split(",").forEach((c) => setKeyValue(customContent, c, ":", c));
101
+ (_c = configFromFile.customContent) === null || _c === void 0 ? void 0 : _c.forEach((c) => setKeyValue(customContent, c, ":", c));
102
+ (_d = cliOptions.customContent) === null || _d === void 0 ? void 0 : _d.forEach((contents) => contents.split(",").forEach((content) => setKeyValue(customContent, content, ":", content)));
128
103
  const cliExtraContent = {};
129
- (_g = cliOptions.extraContent) === null || _g === void 0 ? void 0 : _g.split(",").forEach((x) => setKeyValue(cliExtraContent, x, ":"));
104
+ (_e = cliOptions.extraContent) === null || _e === void 0 ? void 0 : _e.forEach((extras) => extras.split(",").forEach((extra) => setKeyValue(cliExtraContent, extra, ":")));
130
105
  const extraContent = Object.assign(Object.assign({}, configFromFile.extraContent), cliExtraContent);
131
106
  const cliParams = (0, utils_1.omit)(cliOptions, [
132
107
  "label",
@@ -147,11 +122,12 @@ const options = Object.assign(Object.assign(Object.assign({}, defaultOptions), s
147
122
  function exitWithErrorIf(check, error) {
148
123
  if (check) {
149
124
  logger_1.default.error("ERROR: " + error);
150
- commander_1.program.help({ error: true });
125
+ program.help({ error: true });
151
126
  }
152
127
  }
153
128
  if (options.verbose)
154
129
  logger_1.default.enableDebug();
130
+ exitWithErrorIf(!!options.setTimeStamp && !!options.preserveTimeStamp, "Do not set both --preserveTimeStamp and --setTimeStamp");
155
131
  exitWithErrorIf(!!options.registry && !!options.fromRegistry, "Do not set both --registry and --fromRegistry");
156
132
  exitWithErrorIf(!!options.from && !!options.fromRegistry, "Do not set both --from and --fromRegistry");
157
133
  exitWithErrorIf(!!options.registry && !!options.from, "Do not set both --registry and --from");
@@ -202,11 +178,11 @@ if (options.toRegistry && !options.toRegistry.endsWith("/"))
202
178
  options.toRegistry += "/";
203
179
  if (options.fromRegistry && !options.fromRegistry.endsWith("/"))
204
180
  options.fromRegistry += "/";
205
- if (!options.fromRegistry && !((_k = (_j = (_h = options.fromImage) === null || _h === void 0 ? void 0 : _h.split(":")) === null || _j === void 0 ? void 0 : _j[0]) === null || _k === void 0 ? void 0 : _k.includes("/"))) {
181
+ if (!options.fromRegistry && !((_h = (_g = (_f = options.fromImage) === null || _f === void 0 ? void 0 : _f.split(":")) === null || _g === void 0 ? void 0 : _g[0]) === null || _h === void 0 ? void 0 : _h.includes("/"))) {
206
182
  options.fromImage = "library/" + options.fromImage;
207
183
  }
208
184
  Object.keys(options.customContent).forEach((p) => {
209
- exitWithErrorIf(!fs.existsSync(p), "Could not find " + p + " in the base folder " + options.folder);
185
+ exitWithErrorIf(!fs.existsSync(p), `Could not find ${p} in the base folder ${options.folder}`);
210
186
  });
211
187
  if (options.layerCacheFolder) {
212
188
  if (!fs.existsSync(options.layerCacheFolder)) {
@@ -215,7 +191,7 @@ if (options.layerCacheFolder) {
215
191
  fs.mkdirSync(options.layerCacheFolder, { recursive: true });
216
192
  }
217
193
  catch (e) {
218
- exitWithErrorIf(true, "Failed to create layer cache folder");
194
+ exitWithErrorIf(true, `Failed to create layer cache folder ${e}`);
219
195
  }
220
196
  }
221
197
  if (!options.layerCacheFolder.endsWith("/")) {
@@ -223,13 +199,13 @@ if (options.layerCacheFolder) {
223
199
  }
224
200
  }
225
201
  Object.keys(options.extraContent).forEach((k) => {
226
- exitWithErrorIf(!fs.existsSync(options.folder + k), "Could not find `" + k + "` in the folder " + options.folder);
202
+ exitWithErrorIf(!fs.existsSync(options.folder + k), `Could not find '${k}' in the folder ${options.folder}`);
227
203
  });
228
204
  function run(options) {
229
205
  return __awaiter(this, void 0, void 0, function* () {
230
206
  var _a;
231
207
  if (!(yield fse.pathExists(options.folder)))
232
- throw new Error("No such folder: " + options.folder);
208
+ throw new Error(`No such folder: ${options.folder}`);
233
209
  const tmpdir = fs.mkdtempSync(path.join(os.tmpdir(), "containerify-"));
234
210
  logger_1.default.debug("Using " + tmpdir);
235
211
  const fromdir = yield (0, fileutil_1.ensureEmptyDir)(path.join(tmpdir, "from"));
@@ -254,7 +230,7 @@ function run(options) {
254
230
  const toRegistry = yield (0, registry_1.createRegistry)(options.toRegistry, options.toImage, allowInsecure, options.toToken, options.optimisticToRegistryCheck);
255
231
  yield toRegistry.upload(options.toImage, todir, options.doCrossMount, originalManifest, options.fromImage);
256
232
  }
257
- logger_1.default.debug("Deleting " + tmpdir + " ...");
233
+ logger_1.default.debug(`Deleting ${tmpdir} ...`);
258
234
  yield fse.remove(tmpdir);
259
235
  logger_1.default.debug("Done");
260
236
  });
@@ -18,7 +18,7 @@ function isAvailable() {
18
18
  try {
19
19
  yield execAsync("docker -v");
20
20
  }
21
- catch (e) {
21
+ catch (_a) {
22
22
  return false;
23
23
  }
24
24
  return true;
package/lib/logger.js CHANGED
@@ -1,5 +1,4 @@
1
1
  "use strict";
2
- /* eslint-disable no-console */
3
2
  Object.defineProperty(exports, "__esModule", { value: true });
4
3
  let debugEnabled = false;
5
4
  function timeString() {
package/lib/registry.js CHANGED
@@ -130,7 +130,7 @@ function uploadContent(uploadUrl, file, fileConfig, allowInsecure, auth, content
130
130
  }
131
131
  function processToken(registryBaseUrl, allowInsecure, imagePath, token) {
132
132
  return __awaiter(this, void 0, void 0, function* () {
133
- const { hostname } = URL.parse(registryBaseUrl);
133
+ const { hostname } = new URL.URL(registryBaseUrl);
134
134
  const image = (0, utils_1.parseImage)(imagePath);
135
135
  if ((hostname === null || hostname === void 0 ? void 0 : hostname.endsWith(".docker.io")) && !token)
136
136
  return getDockerToken(image.path, allowInsecure);
@@ -140,7 +140,8 @@ function processToken(registryBaseUrl, allowInsecure, imagePath, token) {
140
140
  return getGitLabToken(token, image.path, allowInsecure);
141
141
  if (token.startsWith("Basic "))
142
142
  return token;
143
- if (token.startsWith("ghp_"))
143
+ const githubPrefixes = ["ghp_", "github_pat_", "gho_", "ghu_", "ghs_"];
144
+ if (githubPrefixes.some((prefix) => token.startsWith(prefix)))
144
145
  return "Bearer " + Buffer.from(token).toString("base64");
145
146
  return "Bearer " + token;
146
147
  });
package/lib/types.d.ts CHANGED
@@ -76,6 +76,7 @@ export type Options = {
76
76
  entrypoint: string;
77
77
  labels: Record<string, string>;
78
78
  envs: string[];
79
+ preserveTimeStamp?: boolean;
79
80
  setTimeStamp?: string;
80
81
  verbose?: boolean;
81
82
  allowInsecureRegistries?: boolean;
package/lib/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const VERSION = "3.1.2";
1
+ export declare const VERSION = "3.2.1";
package/lib/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VERSION = void 0;
4
- exports.VERSION = "3.1.2";
4
+ exports.VERSION = "3.2.1";
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "containerify",
3
- "version": "3.1.2",
3
+ "version": "3.2.1",
4
4
  "description": "Build node.js docker images without docker",
5
5
  "main": "./lib/cli.js",
6
6
  "scripts": {
7
7
  "prebuild": "node -p \"'export const VERSION = ' + JSON.stringify(require('./package.json').version) + ';'\" > src/version.ts",
8
8
  "build": "tsc && chmod ugo+x lib/cli.js",
9
- "lint": "eslint . --ext .ts --fix --ignore-path .gitignore",
9
+ "lint": "eslint . --ext .ts --fix",
10
10
  "typecheck": "tsc --noEmit",
11
11
  "watch": "tsc --watch",
12
12
  "check": "npm run lint && npm run typecheck",
@@ -16,7 +16,7 @@
16
16
  "allTests": "npm run integrationTest && npm run registryTest"
17
17
  },
18
18
  "bin": {
19
- "containerify": "./lib/cli.js"
19
+ "containerify": "lib/cli.js"
20
20
  },
21
21
  "author": "Erlend Oftedal <erlend@oftedal.no>",
22
22
  "contributors": [
@@ -25,7 +25,7 @@
25
25
  "license": "Apache-2.0",
26
26
  "repository": {
27
27
  "type": "git",
28
- "url": "https://github.com/eoftedal/containerify.git"
28
+ "url": "git+https://github.com/eoftedal/containerify.git"
29
29
  },
30
30
  "files": [
31
31
  "lib/"
@@ -36,20 +36,23 @@
36
36
  "image"
37
37
  ],
38
38
  "dependencies": {
39
- "commander": "^11.0.0",
40
- "fs-extra": "^11.1.0",
41
- "tar": "^6.1.13"
39
+ "commander": "^13.1.0",
40
+ "fs-extra": "^11.3.0",
41
+ "tar": "^6.2.1"
42
42
  },
43
43
  "devDependencies": {
44
- "@types/fs-extra": "^11.0.1",
45
- "@types/minizlib": "^2.1.4",
46
- "@types/node": "^18.11.19",
47
- "@types/tar": "^6.1.3",
48
- "@typescript-eslint/eslint-plugin": "^5.51.0",
49
- "@typescript-eslint/parser": "^5.51.0",
50
- "eslint": "^8.33.0",
51
- "eslint-config-prettier": "^8.6.0",
52
- "prettier": "^2.8.3",
53
- "typescript": "^5.1.6"
44
+ "@eslint/eslintrc": "^3.3.1",
45
+ "@eslint/js": "^9.23.0",
46
+ "@types/fs-extra": "^11.0.4",
47
+ "@types/minizlib": "^2.1.7",
48
+ "@types/node": "^22.13.9",
49
+ "@types/tar": "^6.1.13",
50
+ "@typescript-eslint/eslint-plugin": "^8.26.0",
51
+ "@typescript-eslint/parser": "^8.26",
52
+ "eslint": "^9.21.0",
53
+ "eslint-config-prettier": "^10.1.1",
54
+ "globals": "^16.0.0",
55
+ "prettier": "^3.5.3",
56
+ "typescript": "^5.8.2"
54
57
  }
55
58
  }