@regressionproof/snapshotter 0.7.1 → 0.7.3

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.
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const fs_1 = require("fs");
7
7
  const path_1 = __importDefault(require("path"));
8
+ const SnapshotterState_js_1 = __importDefault(require("../utilities/SnapshotterState.js"));
8
9
  class ErrorHandler {
9
10
  constructor() { }
10
11
  static Handler() {
@@ -22,8 +23,7 @@ class ErrorHandler {
22
23
  }
23
24
  }
24
25
  persistError(mirrorPath, err) {
25
- const snapshotterDir = path_1.default.join(mirrorPath, '.snapshotter');
26
- (0, fs_1.mkdirSync)(snapshotterDir, { recursive: true });
26
+ SnapshotterState_js_1.default.EnsureStateDir(mirrorPath);
27
27
  const errorPath = this.getErrorFilePath(mirrorPath);
28
28
  const errorData = {
29
29
  message: err instanceof Error ? err.message : String(err),
@@ -39,7 +39,8 @@ class ErrorHandler {
39
39
  }
40
40
  }
41
41
  getErrorFilePath(mirrorPath) {
42
- return path_1.default.join(mirrorPath, '.snapshotter', ErrorHandler.ERROR_FILE_NAME);
42
+ const stateDir = SnapshotterState_js_1.default.GetStateDir(mirrorPath);
43
+ return path_1.default.join(stateDir, ErrorHandler.ERROR_FILE_NAME);
43
44
  }
44
45
  }
45
46
  ErrorHandler.ERROR_FILE_NAME = 'lastError.json';
@@ -1,5 +1,6 @@
1
- import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync, } from 'fs';
1
+ import { existsSync, readFileSync, unlinkSync, writeFileSync } from 'fs';
2
2
  import path from 'path';
3
+ import SnapshotterState from '../utilities/SnapshotterState.js.js';
3
4
  class ErrorHandler {
4
5
  constructor() { }
5
6
  static Handler() {
@@ -17,8 +18,7 @@ class ErrorHandler {
17
18
  }
18
19
  }
19
20
  persistError(mirrorPath, err) {
20
- const snapshotterDir = path.join(mirrorPath, '.snapshotter');
21
- mkdirSync(snapshotterDir, { recursive: true });
21
+ SnapshotterState.EnsureStateDir(mirrorPath);
22
22
  const errorPath = this.getErrorFilePath(mirrorPath);
23
23
  const errorData = {
24
24
  message: err instanceof Error ? err.message : String(err),
@@ -34,7 +34,8 @@ class ErrorHandler {
34
34
  }
35
35
  }
36
36
  getErrorFilePath(mirrorPath) {
37
- return path.join(mirrorPath, '.snapshotter', ErrorHandler.ERROR_FILE_NAME);
37
+ const stateDir = SnapshotterState.GetStateDir(mirrorPath);
38
+ return path.join(stateDir, ErrorHandler.ERROR_FILE_NAME);
38
39
  }
39
40
  }
40
41
  ErrorHandler.ERROR_FILE_NAME = 'lastError.json';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,83 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { existsSync, unlinkSync, writeFileSync } from 'fs';
11
+ import path from 'path';
12
+ import { buildLog } from '@sprucelabs/spruce-skill-utils';
13
+ import ErrorHandler from '../components/ErrorHandler.js.js';
14
+ import { gitPush } from '../git.js.js';
15
+ import SnapshotterState from '../utilities/SnapshotterState.js.js';
16
+ const LOCK_FILE_NAME = 'push.lock';
17
+ const PENDING_FILE_NAME = 'push.pending';
18
+ const log = buildLog('Snapshotter');
19
+ function main() {
20
+ return __awaiter(this, void 0, void 0, function* () {
21
+ const mirrorPath = getEnvOrExit('MIRROR_PATH');
22
+ const remoteUrl = getEnvOrExit('REMOTE_URL');
23
+ const remoteToken = getEnvOrExit('REMOTE_TOKEN');
24
+ const stateDir = SnapshotterState.EnsureStateDir(mirrorPath);
25
+ const lockPath = path.join(stateDir, LOCK_FILE_NAME);
26
+ const pendingPath = path.join(stateDir, PENDING_FILE_NAME);
27
+ if (existsSync(lockPath)) {
28
+ writeFileSync(pendingPath, new Date().toISOString());
29
+ log.info('Push already running, marked pending', mirrorPath);
30
+ return;
31
+ }
32
+ try {
33
+ writeFileSync(lockPath, process.pid.toString());
34
+ const remote = {
35
+ url: remoteUrl,
36
+ token: remoteToken,
37
+ };
38
+ yield processLoop(mirrorPath, remote, pendingPath);
39
+ }
40
+ finally {
41
+ if (existsSync(lockPath)) {
42
+ unlinkSync(lockPath);
43
+ }
44
+ }
45
+ });
46
+ }
47
+ function processLoop(mirrorPath, remote, pendingPath) {
48
+ return __awaiter(this, void 0, void 0, function* () {
49
+ while (true) {
50
+ if (existsSync(pendingPath)) {
51
+ unlinkSync(pendingPath);
52
+ }
53
+ try {
54
+ log.info('Push starting', remote.url);
55
+ yield gitPush(mirrorPath, remote, log);
56
+ log.info('Push completed', remote.url);
57
+ ErrorHandler.Handler().clearError(mirrorPath);
58
+ }
59
+ catch (err) {
60
+ const message = err instanceof Error ? err.message : String(err);
61
+ log.error('Push failed', message);
62
+ ErrorHandler.Handler().persistError(mirrorPath, err);
63
+ writeFileSync(pendingPath, new Date().toISOString());
64
+ return;
65
+ }
66
+ if (!existsSync(pendingPath)) {
67
+ return;
68
+ }
69
+ }
70
+ });
71
+ }
72
+ function getEnvOrExit(name) {
73
+ const value = process.env[name];
74
+ if (!value) {
75
+ console.error(`Missing required env var: ${name}`);
76
+ process.exit(1);
77
+ }
78
+ return value;
79
+ }
80
+ main().catch((err) => {
81
+ console.error('Push script failed:', err);
82
+ process.exit(1);
83
+ });
@@ -17,19 +17,19 @@ const PENDING_FILE_NAME = 'pending.json';
17
17
  const log = buildLog('Snapshotter');
18
18
  function main() {
19
19
  return __awaiter(this, void 0, void 0, function* () {
20
- const snapshotterDir = process.argv[2];
21
- if (!snapshotterDir) {
22
- console.error('Usage: runSnapshot <snapshotter-dir>');
20
+ const stateDir = process.argv[2];
21
+ if (!stateDir) {
22
+ console.error('Usage: runSnapshot <state-dir>');
23
23
  process.exit(1);
24
24
  }
25
- const lockPath = path.join(snapshotterDir, LOCK_FILE_NAME);
25
+ const lockPath = path.join(stateDir, LOCK_FILE_NAME);
26
26
  if (existsSync(lockPath)) {
27
27
  log.info('Another snapshot is running, exiting');
28
28
  process.exit(0);
29
29
  }
30
30
  try {
31
31
  writeFileSync(lockPath, process.pid.toString());
32
- yield processLoop(snapshotterDir);
32
+ yield processLoop(stateDir);
33
33
  }
34
34
  finally {
35
35
  if (existsSync(lockPath)) {
@@ -38,9 +38,9 @@ function main() {
38
38
  }
39
39
  });
40
40
  }
41
- function processLoop(snapshotterDir) {
41
+ function processLoop(stateDir) {
42
42
  return __awaiter(this, void 0, void 0, function* () {
43
- const pendingPath = path.join(snapshotterDir, PENDING_FILE_NAME);
43
+ const pendingPath = path.join(stateDir, PENDING_FILE_NAME);
44
44
  while (existsSync(pendingPath)) {
45
45
  const options = JSON.parse(readFileSync(pendingPath, 'utf-8'));
46
46
  unlinkSync(pendingPath);
@@ -1,7 +1,8 @@
1
1
  import { spawn } from 'child_process';
2
- import { mkdirSync, writeFileSync } from 'fs';
2
+ import { writeFileSync } from 'fs';
3
3
  import path from 'path';
4
4
  import { buildLog } from '@sprucelabs/spruce-skill-utils';
5
+ import SnapshotterState from '../utilities/SnapshotterState.js.js';
5
6
  export default class AsyncStrategy {
6
7
  constructor() {
7
8
  this.log = buildLog('Snapshotter');
@@ -11,19 +12,18 @@ export default class AsyncStrategy {
11
12
  return new this();
12
13
  }
13
14
  execute(options) {
14
- const snapshotterDir = this.writeOptionsFile(options);
15
- this.spawnSnapshotProcess(snapshotterDir);
15
+ const stateDir = this.writeOptionsFile(options);
16
+ this.spawnSnapshotProcess(stateDir);
16
17
  this.log.info('Snapshot queued (running in background)', options.mirrorPath);
17
18
  }
18
19
  writeOptionsFile(options) {
19
- const snapshotterDir = path.join(options.mirrorPath, '.snapshotter');
20
- mkdirSync(snapshotterDir, { recursive: true });
21
- const optionsPath = path.join(snapshotterDir, 'pending.json');
20
+ const stateDir = SnapshotterState.EnsureStateDir(options.mirrorPath);
21
+ const optionsPath = path.join(stateDir, 'pending.json');
22
22
  writeFileSync(optionsPath, JSON.stringify(options, null, 2));
23
- return snapshotterDir;
23
+ return stateDir;
24
24
  }
25
- spawnSnapshotProcess(snapshotterDir) {
26
- const child = spawn('node', [this.scriptPath, snapshotterDir], {
25
+ spawnSnapshotProcess(stateDir) {
26
+ const child = spawn('node', [this.scriptPath, stateDir], {
27
27
  detached: true,
28
28
  stdio: 'ignore',
29
29
  });
@@ -2,7 +2,9 @@ import { SnapshotOptions } from '../snapshotter.types.js';
2
2
  import SnapshotStrategy from './SnapshotStrategy.js';
3
3
  export default class SyncStrategy implements SnapshotStrategy {
4
4
  private log;
5
+ private pushScriptPath;
5
6
  private constructor();
6
7
  static Strategy(): SyncStrategy;
7
8
  execute(options: SnapshotOptions): Promise<void>;
9
+ private spawnPushProcess;
8
10
  }
@@ -7,14 +7,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
+ import { spawn } from 'child_process';
11
+ import path from 'path';
10
12
  import { buildLog } from '@sprucelabs/spruce-skill-utils';
11
13
  import ErrorHandler from '../components/ErrorHandler.js.js';
12
14
  import FileSyncer from '../components/FileSyncer.js.js';
13
15
  import TestResultsWriter from '../components/TestResultsWriter.js.js';
14
- import { gitCommit, gitPush } from '../git.js.js';
16
+ import { gitCommit } from '../git.js.js';
17
+ import SnapshotterState from '../utilities/SnapshotterState.js.js';
15
18
  export default class SyncStrategy {
16
19
  constructor() {
17
20
  this.log = buildLog('Snapshotter');
21
+ this.pushScriptPath = path.join(__dirname, '..', 'scripts', 'runPush.js');
18
22
  }
19
23
  static Strategy() {
20
24
  return new this();
@@ -27,6 +31,7 @@ export default class SyncStrategy {
27
31
  this.log.info('Starting snapshot', sourcePath, mirrorPath);
28
32
  try {
29
33
  yield FileSyncer.Syncer().sync(sourcePath, mirrorPath);
34
+ SnapshotterState.CleanupLegacyMirrorState(mirrorPath);
30
35
  this.log.info('Files synced', mirrorPath);
31
36
  TestResultsWriter.Writer().write(mirrorPath, testResults);
32
37
  this.log.info('Test results saved', mirrorPath);
@@ -36,10 +41,8 @@ export default class SyncStrategy {
36
41
  ErrorHandler.Handler().clearError(mirrorPath);
37
42
  return;
38
43
  }
39
- this.log.info('Commit created, pushing', remote.url);
40
- yield gitPush(mirrorPath, remote, this.log);
41
- this.log.info('Push completed', remote.url);
42
- ErrorHandler.Handler().clearError(mirrorPath);
44
+ this.log.info('Commit created, queueing push', remote.url);
45
+ this.spawnPushProcess(mirrorPath, remote);
43
46
  }
44
47
  catch (err) {
45
48
  const message = err instanceof Error ? err.message : String(err);
@@ -49,4 +52,12 @@ export default class SyncStrategy {
49
52
  }
50
53
  });
51
54
  }
55
+ spawnPushProcess(mirrorPath, remote) {
56
+ const child = spawn('node', [this.pushScriptPath], {
57
+ detached: true,
58
+ stdio: 'ignore',
59
+ env: Object.assign(Object.assign({}, process.env), { MIRROR_PATH: mirrorPath, REMOTE_URL: remote.url, REMOTE_TOKEN: remote.token }),
60
+ });
61
+ child.unref();
62
+ }
52
63
  }
@@ -0,0 +1,8 @@
1
+ export default class SnapshotterState {
2
+ private static readonly STATE_DIR_NAME;
3
+ private static readonly LEGACY_RUNTIME_FILES;
4
+ private constructor();
5
+ static GetStateDir(mirrorPath: string): string;
6
+ static EnsureStateDir(mirrorPath: string): string;
7
+ static CleanupLegacyMirrorState(mirrorPath: string): void;
8
+ }
@@ -0,0 +1,34 @@
1
+ import { existsSync, mkdirSync, unlinkSync } from 'fs';
2
+ import path from 'path';
3
+ class SnapshotterState {
4
+ constructor() { }
5
+ static GetStateDir(mirrorPath) {
6
+ return path.join(path.dirname(mirrorPath), SnapshotterState.STATE_DIR_NAME);
7
+ }
8
+ static EnsureStateDir(mirrorPath) {
9
+ const stateDir = SnapshotterState.GetStateDir(mirrorPath);
10
+ mkdirSync(stateDir, { recursive: true });
11
+ return stateDir;
12
+ }
13
+ static CleanupLegacyMirrorState(mirrorPath) {
14
+ const legacyDir = path.join(mirrorPath, SnapshotterState.STATE_DIR_NAME);
15
+ if (!existsSync(legacyDir)) {
16
+ return;
17
+ }
18
+ for (const file of SnapshotterState.LEGACY_RUNTIME_FILES) {
19
+ const filePath = path.join(legacyDir, file);
20
+ if (existsSync(filePath)) {
21
+ unlinkSync(filePath);
22
+ }
23
+ }
24
+ }
25
+ }
26
+ SnapshotterState.STATE_DIR_NAME = '.snapshotter';
27
+ SnapshotterState.LEGACY_RUNTIME_FILES = [
28
+ 'push.lock',
29
+ 'push.pending',
30
+ 'lastError.json',
31
+ 'snapshot.lock',
32
+ 'pending.json',
33
+ ];
34
+ export default SnapshotterState;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const fs_1 = require("fs");
7
+ const path_1 = __importDefault(require("path"));
8
+ const spruce_skill_utils_1 = require("@sprucelabs/spruce-skill-utils");
9
+ const ErrorHandler_js_1 = __importDefault(require("../components/ErrorHandler.js"));
10
+ const git_js_1 = require("../git.js");
11
+ const SnapshotterState_js_1 = __importDefault(require("../utilities/SnapshotterState.js"));
12
+ const LOCK_FILE_NAME = 'push.lock';
13
+ const PENDING_FILE_NAME = 'push.pending';
14
+ const log = (0, spruce_skill_utils_1.buildLog)('Snapshotter');
15
+ async function main() {
16
+ const mirrorPath = getEnvOrExit('MIRROR_PATH');
17
+ const remoteUrl = getEnvOrExit('REMOTE_URL');
18
+ const remoteToken = getEnvOrExit('REMOTE_TOKEN');
19
+ const stateDir = SnapshotterState_js_1.default.EnsureStateDir(mirrorPath);
20
+ const lockPath = path_1.default.join(stateDir, LOCK_FILE_NAME);
21
+ const pendingPath = path_1.default.join(stateDir, PENDING_FILE_NAME);
22
+ if ((0, fs_1.existsSync)(lockPath)) {
23
+ (0, fs_1.writeFileSync)(pendingPath, new Date().toISOString());
24
+ log.info('Push already running, marked pending', mirrorPath);
25
+ return;
26
+ }
27
+ try {
28
+ (0, fs_1.writeFileSync)(lockPath, process.pid.toString());
29
+ const remote = {
30
+ url: remoteUrl,
31
+ token: remoteToken,
32
+ };
33
+ await processLoop(mirrorPath, remote, pendingPath);
34
+ }
35
+ finally {
36
+ if ((0, fs_1.existsSync)(lockPath)) {
37
+ (0, fs_1.unlinkSync)(lockPath);
38
+ }
39
+ }
40
+ }
41
+ async function processLoop(mirrorPath, remote, pendingPath) {
42
+ while (true) {
43
+ if ((0, fs_1.existsSync)(pendingPath)) {
44
+ (0, fs_1.unlinkSync)(pendingPath);
45
+ }
46
+ try {
47
+ log.info('Push starting', remote.url);
48
+ await (0, git_js_1.gitPush)(mirrorPath, remote, log);
49
+ log.info('Push completed', remote.url);
50
+ ErrorHandler_js_1.default.Handler().clearError(mirrorPath);
51
+ }
52
+ catch (err) {
53
+ const message = err instanceof Error ? err.message : String(err);
54
+ log.error('Push failed', message);
55
+ ErrorHandler_js_1.default.Handler().persistError(mirrorPath, err);
56
+ (0, fs_1.writeFileSync)(pendingPath, new Date().toISOString());
57
+ return;
58
+ }
59
+ if (!(0, fs_1.existsSync)(pendingPath)) {
60
+ return;
61
+ }
62
+ }
63
+ }
64
+ function getEnvOrExit(name) {
65
+ const value = process.env[name];
66
+ if (!value) {
67
+ console.error(`Missing required env var: ${name}`);
68
+ process.exit(1);
69
+ }
70
+ return value;
71
+ }
72
+ main().catch((err) => {
73
+ console.error('Push script failed:', err);
74
+ process.exit(1);
75
+ });
@@ -12,19 +12,19 @@ const LOCK_FILE_NAME = 'snapshot.lock';
12
12
  const PENDING_FILE_NAME = 'pending.json';
13
13
  const log = (0, spruce_skill_utils_1.buildLog)('Snapshotter');
14
14
  async function main() {
15
- const snapshotterDir = process.argv[2];
16
- if (!snapshotterDir) {
17
- console.error('Usage: runSnapshot <snapshotter-dir>');
15
+ const stateDir = process.argv[2];
16
+ if (!stateDir) {
17
+ console.error('Usage: runSnapshot <state-dir>');
18
18
  process.exit(1);
19
19
  }
20
- const lockPath = path_1.default.join(snapshotterDir, LOCK_FILE_NAME);
20
+ const lockPath = path_1.default.join(stateDir, LOCK_FILE_NAME);
21
21
  if ((0, fs_1.existsSync)(lockPath)) {
22
22
  log.info('Another snapshot is running, exiting');
23
23
  process.exit(0);
24
24
  }
25
25
  try {
26
26
  (0, fs_1.writeFileSync)(lockPath, process.pid.toString());
27
- await processLoop(snapshotterDir);
27
+ await processLoop(stateDir);
28
28
  }
29
29
  finally {
30
30
  if ((0, fs_1.existsSync)(lockPath)) {
@@ -32,8 +32,8 @@ async function main() {
32
32
  }
33
33
  }
34
34
  }
35
- async function processLoop(snapshotterDir) {
36
- const pendingPath = path_1.default.join(snapshotterDir, PENDING_FILE_NAME);
35
+ async function processLoop(stateDir) {
36
+ const pendingPath = path_1.default.join(stateDir, PENDING_FILE_NAME);
37
37
  while ((0, fs_1.existsSync)(pendingPath)) {
38
38
  const options = JSON.parse((0, fs_1.readFileSync)(pendingPath, 'utf-8'));
39
39
  (0, fs_1.unlinkSync)(pendingPath);
@@ -7,6 +7,7 @@ const child_process_1 = require("child_process");
7
7
  const fs_1 = require("fs");
8
8
  const path_1 = __importDefault(require("path"));
9
9
  const spruce_skill_utils_1 = require("@sprucelabs/spruce-skill-utils");
10
+ const SnapshotterState_js_1 = __importDefault(require("../utilities/SnapshotterState.js"));
10
11
  class AsyncStrategy {
11
12
  constructor() {
12
13
  this.log = (0, spruce_skill_utils_1.buildLog)('Snapshotter');
@@ -16,19 +17,18 @@ class AsyncStrategy {
16
17
  return new this();
17
18
  }
18
19
  execute(options) {
19
- const snapshotterDir = this.writeOptionsFile(options);
20
- this.spawnSnapshotProcess(snapshotterDir);
20
+ const stateDir = this.writeOptionsFile(options);
21
+ this.spawnSnapshotProcess(stateDir);
21
22
  this.log.info('Snapshot queued (running in background)', options.mirrorPath);
22
23
  }
23
24
  writeOptionsFile(options) {
24
- const snapshotterDir = path_1.default.join(options.mirrorPath, '.snapshotter');
25
- (0, fs_1.mkdirSync)(snapshotterDir, { recursive: true });
26
- const optionsPath = path_1.default.join(snapshotterDir, 'pending.json');
25
+ const stateDir = SnapshotterState_js_1.default.EnsureStateDir(options.mirrorPath);
26
+ const optionsPath = path_1.default.join(stateDir, 'pending.json');
27
27
  (0, fs_1.writeFileSync)(optionsPath, JSON.stringify(options, null, 2));
28
- return snapshotterDir;
28
+ return stateDir;
29
29
  }
30
- spawnSnapshotProcess(snapshotterDir) {
31
- const child = (0, child_process_1.spawn)('node', [this.scriptPath, snapshotterDir], {
30
+ spawnSnapshotProcess(stateDir) {
31
+ const child = (0, child_process_1.spawn)('node', [this.scriptPath, stateDir], {
32
32
  detached: true,
33
33
  stdio: 'ignore',
34
34
  });
@@ -2,7 +2,9 @@ import { SnapshotOptions } from '../snapshotter.types.js';
2
2
  import SnapshotStrategy from './SnapshotStrategy.js';
3
3
  export default class SyncStrategy implements SnapshotStrategy {
4
4
  private log;
5
+ private pushScriptPath;
5
6
  private constructor();
6
7
  static Strategy(): SyncStrategy;
7
8
  execute(options: SnapshotOptions): Promise<void>;
9
+ private spawnPushProcess;
8
10
  }
@@ -3,14 +3,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ const child_process_1 = require("child_process");
7
+ const path_1 = __importDefault(require("path"));
6
8
  const spruce_skill_utils_1 = require("@sprucelabs/spruce-skill-utils");
7
9
  const ErrorHandler_js_1 = __importDefault(require("../components/ErrorHandler.js"));
8
10
  const FileSyncer_js_1 = __importDefault(require("../components/FileSyncer.js"));
9
11
  const TestResultsWriter_js_1 = __importDefault(require("../components/TestResultsWriter.js"));
10
12
  const git_js_1 = require("../git.js");
13
+ const SnapshotterState_js_1 = __importDefault(require("../utilities/SnapshotterState.js"));
11
14
  class SyncStrategy {
12
15
  constructor() {
13
16
  this.log = (0, spruce_skill_utils_1.buildLog)('Snapshotter');
17
+ this.pushScriptPath = path_1.default.join(__dirname, '..', 'scripts', 'runPush.js');
14
18
  }
15
19
  static Strategy() {
16
20
  return new this();
@@ -21,6 +25,7 @@ class SyncStrategy {
21
25
  this.log.info('Starting snapshot', sourcePath, mirrorPath);
22
26
  try {
23
27
  await FileSyncer_js_1.default.Syncer().sync(sourcePath, mirrorPath);
28
+ SnapshotterState_js_1.default.CleanupLegacyMirrorState(mirrorPath);
24
29
  this.log.info('Files synced', mirrorPath);
25
30
  TestResultsWriter_js_1.default.Writer().write(mirrorPath, testResults);
26
31
  this.log.info('Test results saved', mirrorPath);
@@ -30,10 +35,8 @@ class SyncStrategy {
30
35
  ErrorHandler_js_1.default.Handler().clearError(mirrorPath);
31
36
  return;
32
37
  }
33
- this.log.info('Commit created, pushing', remote.url);
34
- await (0, git_js_1.gitPush)(mirrorPath, remote, this.log);
35
- this.log.info('Push completed', remote.url);
36
- ErrorHandler_js_1.default.Handler().clearError(mirrorPath);
38
+ this.log.info('Commit created, queueing push', remote.url);
39
+ this.spawnPushProcess(mirrorPath, remote);
37
40
  }
38
41
  catch (err) {
39
42
  const message = err instanceof Error ? err.message : String(err);
@@ -42,5 +45,18 @@ class SyncStrategy {
42
45
  throw err;
43
46
  }
44
47
  }
48
+ spawnPushProcess(mirrorPath, remote) {
49
+ const child = (0, child_process_1.spawn)('node', [this.pushScriptPath], {
50
+ detached: true,
51
+ stdio: 'ignore',
52
+ env: {
53
+ ...process.env,
54
+ MIRROR_PATH: mirrorPath,
55
+ REMOTE_URL: remote.url,
56
+ REMOTE_TOKEN: remote.token,
57
+ },
58
+ });
59
+ child.unref();
60
+ }
45
61
  }
46
62
  exports.default = SyncStrategy;
@@ -0,0 +1,8 @@
1
+ export default class SnapshotterState {
2
+ private static readonly STATE_DIR_NAME;
3
+ private static readonly LEGACY_RUNTIME_FILES;
4
+ private constructor();
5
+ static GetStateDir(mirrorPath: string): string;
6
+ static EnsureStateDir(mirrorPath: string): string;
7
+ static CleanupLegacyMirrorState(mirrorPath: string): void;
8
+ }
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const fs_1 = require("fs");
7
+ const path_1 = __importDefault(require("path"));
8
+ class SnapshotterState {
9
+ constructor() { }
10
+ static GetStateDir(mirrorPath) {
11
+ return path_1.default.join(path_1.default.dirname(mirrorPath), SnapshotterState.STATE_DIR_NAME);
12
+ }
13
+ static EnsureStateDir(mirrorPath) {
14
+ const stateDir = SnapshotterState.GetStateDir(mirrorPath);
15
+ (0, fs_1.mkdirSync)(stateDir, { recursive: true });
16
+ return stateDir;
17
+ }
18
+ static CleanupLegacyMirrorState(mirrorPath) {
19
+ const legacyDir = path_1.default.join(mirrorPath, SnapshotterState.STATE_DIR_NAME);
20
+ if (!(0, fs_1.existsSync)(legacyDir)) {
21
+ return;
22
+ }
23
+ for (const file of SnapshotterState.LEGACY_RUNTIME_FILES) {
24
+ const filePath = path_1.default.join(legacyDir, file);
25
+ if ((0, fs_1.existsSync)(filePath)) {
26
+ (0, fs_1.unlinkSync)(filePath);
27
+ }
28
+ }
29
+ }
30
+ }
31
+ SnapshotterState.STATE_DIR_NAME = '.snapshotter';
32
+ SnapshotterState.LEGACY_RUNTIME_FILES = [
33
+ 'push.lock',
34
+ 'push.pending',
35
+ 'lastError.json',
36
+ 'snapshot.lock',
37
+ 'pending.json',
38
+ ];
39
+ exports.default = SnapshotterState;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@regressionproof/snapshotter",
3
- "version": "0.7.1",
3
+ "version": "0.7.3",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -94,5 +94,5 @@
94
94
  "@sprucelabs/spruce-core-schemas": "^42.1.3",
95
95
  "@sprucelabs/spruce-skill-utils": "^34.0.3"
96
96
  },
97
- "gitHead": "c38dea336a4653790787044ca8b4209a9e5352fa"
97
+ "gitHead": "11e6ee4957dfa9a0160dac49bb007f196c9beab4"
98
98
  }