hammerkit 1.12.0 → 1.13.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.
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.removeOrphanedContainers = exports.isProcessAlive = exports.isOrphanedContainer = void 0;
3
+ exports.removeOrphanedContainers = exports.isDockerUnreachable = exports.isProcessAlive = exports.isOrphanedContainer = void 0;
4
4
  const os_1 = require("os");
5
5
  const remove_container_1 = require("./remove-container");
6
6
  // A hammerkit container nothing will remove any more: a task container (they
@@ -41,8 +41,26 @@ function isProcessAlive(pid) {
41
41
  }
42
42
  }
43
43
  exports.isProcessAlive = isProcessAlive;
44
+ // No daemon listens on the socket or named pipe (ENOENT, or ECONNREFUSED for a
45
+ // socket nothing serves). Other failures, such as a permission error, are real.
46
+ function isDockerUnreachable(e) {
47
+ return e?.syscall === 'connect' && (e.code === 'ENOENT' || e.code === 'ECONNREFUSED');
48
+ }
49
+ exports.isDockerUnreachable = isDockerUnreachable;
50
+ // Without a Docker daemon there is no container left behind, so a machine that
51
+ // has none (a Windows runner without containers, a laptop with Docker stopped)
52
+ // cleans without error.
44
53
  async function removeOrphanedContainers(docker) {
45
- const containers = await docker.listContainers({ all: true, filters: { label: ['app=hammerkit'] } });
54
+ let containers;
55
+ try {
56
+ containers = await docker.listContainers({ all: true, filters: { label: ['app=hammerkit'] } });
57
+ }
58
+ catch (e) {
59
+ if (isDockerUnreachable(e)) {
60
+ return [];
61
+ }
62
+ throw e;
63
+ }
46
64
  const orphaned = containers.filter((c) => isOrphanedContainer(c, isProcessAlive));
47
65
  for (const container of orphaned) {
48
66
  await (0, remove_container_1.removeContainer)(docker.getContainer(container.Id));
package/dist/program.js CHANGED
@@ -277,12 +277,17 @@ async function getProgram(environment, argv) {
277
277
  .default('checksum')
278
278
  .choices(['checksum', 'modify-date', 'none']))
279
279
  .addOption(new commander_1.Option('--json', 'emit the explanation as JSON').default(false))
280
+ .addOption(new commander_1.Option('--check', 'exit with code 1 when any task would be a cache miss').default(false))
280
281
  .action(async (task, options) => {
281
282
  try {
282
283
  const cli = await createCli(fileName, environment, task ? { taskName: task, environmentName: options.env ?? null } : parseWorkLabelScope(options));
283
284
  const explanations = await cli.explain({ cacheDefault: options.cache });
285
+ const missed = explanations.filter((explanation) => explanation.status === 'miss');
284
286
  if (options.json) {
285
287
  environment.stdout.write(`${JSON.stringify(explanations, null, 2)}\n`);
288
+ if (options.check && missed.length > 0) {
289
+ program.error('', { exitCode: 1 });
290
+ }
286
291
  return;
287
292
  }
288
293
  for (const explanation of explanations) {
@@ -296,6 +301,9 @@ async function getProgram(environment, argv) {
296
301
  (0, log_1.printProperty)(environment, 'cause', (0, explain_1.describeCause)(cause));
297
302
  }
298
303
  }
304
+ if (options.check && missed.length > 0) {
305
+ program.error(`${missed.length} of ${explanations.length} tasks would be a cache miss`, { exitCode: 1 });
306
+ }
299
307
  }
300
308
  catch (e) {
301
309
  if (e instanceof commander_1.CommanderError) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "hammerkit",
3
3
  "description": "Containerized build tool with incremental caching that runs the same build file locally, in Docker and on Kubernetes.",
4
- "version": "1.12.0",
4
+ "version": "1.13.1",
5
5
  "keywords": [
6
6
  "build",
7
7
  "build-tool",