Skip to content

Commit e13e3e8

Browse files
authored
Merge pull request #12 from getappmap/fix/most-recent-archive
fix: Choose the most recent archive
2 parents 7ec6ea8 + 81ff649 commit e13e3e8

File tree

11 files changed

+162
-45
lines changed

11 files changed

+162
-45
lines changed

dist/index.js

Lines changed: 70 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
3939
});
4040
};
4141
Object.defineProperty(exports, "__esModule", ({ value: true }));
42-
const fs_1 = __nccwpck_require__(7147);
43-
const glob_1 = __nccwpck_require__(5029);
4442
const path_1 = __nccwpck_require__(1017);
4543
const executeCommand_1 = __nccwpck_require__(3285);
4644
const log_1 = __importStar(__nccwpck_require__(1285));
45+
const locateArchiveFile_1 = __nccwpck_require__(1767);
4746
function applyCommand(command) {
4847
return __awaiter(this, void 0, void 0, function* () {
4948
if (!command)
@@ -67,14 +66,7 @@ class Archiver {
6766
if (revision)
6867
archiveCommand += ` --revision ${revision}`;
6968
yield (0, executeCommand_1.executeCommand)(archiveCommand);
70-
const archiveFiles = (yield (0, glob_1.glob)((0, path_1.join)('.appmap', 'archive', '**', '*.tar'), { dot: true })).filter(file => (0, fs_1.existsSync)(file));
71-
if (archiveFiles.length === 0) {
72-
throw new Error(`No AppMap archives found in ${process.cwd()}`);
73-
}
74-
if (archiveFiles.length > 1) {
75-
(0, log_1.default)(log_1.LogLevel.Warn, `Multiple AppMap archives found in ${process.cwd()}`);
76-
}
77-
const archiveFile = archiveFiles.pop();
69+
const archiveFile = yield (0, locateArchiveFile_1.locateArchiveFile)('.');
7870
(0, log_1.default)(log_1.LogLevel.Debug, `Processing AppMap archive ${archiveFile}`);
7971
// e.g. .appmap/archive/full
8072
const dir = (0, path_1.dirname)(archiveFile);
@@ -171,8 +163,10 @@ function executeCommand(cmd, printCommand = (0, verbose_1.default)(), printStdou
171163
});
172164
}
173165
return new Promise((resolve, reject) => {
174-
command.addListener('exit', code => {
175-
if (code === 0) {
166+
command.addListener('exit', (code, signal) => {
167+
if (signal || code === 0) {
168+
if (signal)
169+
(0, log_1.default)(log_1.LogLevel.Info, `Command killed by signal ${signal}`);
176170
resolve(result.join(''));
177171
}
178172
else {
@@ -259,6 +253,70 @@ if (require.main === require.cache[eval('__filename')]) {
259253
}
260254

261255

256+
/***/ }),
257+
258+
/***/ 1767:
259+
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
260+
261+
"use strict";
262+
263+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
264+
if (k2 === undefined) k2 = k;
265+
var desc = Object.getOwnPropertyDescriptor(m, k);
266+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
267+
desc = { enumerable: true, get: function() { return m[k]; } };
268+
}
269+
Object.defineProperty(o, k2, desc);
270+
}) : (function(o, m, k, k2) {
271+
if (k2 === undefined) k2 = k;
272+
o[k2] = m[k];
273+
}));
274+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
275+
Object.defineProperty(o, "default", { enumerable: true, value: v });
276+
}) : function(o, v) {
277+
o["default"] = v;
278+
});
279+
var __importStar = (this && this.__importStar) || function (mod) {
280+
if (mod && mod.__esModule) return mod;
281+
var result = {};
282+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
283+
__setModuleDefault(result, mod);
284+
return result;
285+
};
286+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
287+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
288+
return new (P || (P = Promise))(function (resolve, reject) {
289+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
290+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
291+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
292+
step((generator = generator.apply(thisArg, _arguments || [])).next());
293+
});
294+
};
295+
Object.defineProperty(exports, "__esModule", ({ value: true }));
296+
exports.locateArchiveFile = void 0;
297+
const fs_1 = __nccwpck_require__(7147);
298+
const glob_1 = __nccwpck_require__(5029);
299+
const path_1 = __nccwpck_require__(1017);
300+
const log_1 = __importStar(__nccwpck_require__(1285));
301+
const promises_1 = __nccwpck_require__(3292);
302+
function locateArchiveFile(workDir) {
303+
return __awaiter(this, void 0, void 0, function* () {
304+
const archiveFiles = (yield (0, glob_1.glob)((0, path_1.join)(workDir, '.appmap', 'archive', '**', '*.tar'), { dot: true })).filter(file => (0, fs_1.existsSync)(file));
305+
const archiveFileTimes = new Map();
306+
yield Promise.all(archiveFiles.map((file) => __awaiter(this, void 0, void 0, function* () { return archiveFileTimes.set(file, (yield (0, promises_1.stat)(file)).mtimeMs); })));
307+
archiveFiles.sort((a, b) => archiveFileTimes.get(b) - archiveFileTimes.get(a));
308+
if (archiveFiles.length === 0)
309+
throw new Error(`No AppMap archives found in ${(0, path_1.join)(process.cwd(), workDir)}`);
310+
const result = archiveFiles.shift();
311+
if (archiveFiles.length > 1) {
312+
(0, log_1.default)(log_1.LogLevel.Warn, `Multiple AppMap archives found in ${(0, path_1.join)(process.cwd(), workDir)}.\nI'll upload the most recent one, which is ${result}.`);
313+
}
314+
return result;
315+
});
316+
}
317+
exports.locateArchiveFile = locateArchiveFile;
318+
319+
262320
/***/ }),
263321

264322
/***/ 1285:

dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
"main": "build/index.js",
77
"scripts": {
88
"build": "tsc",
9-
"test": "jest",
10-
"appmap": "appmap-agent-js -- jest --no-cache",
9+
"test": "jest --runInBand",
10+
"appmap": "appmap-agent-js -- jest --no-cache --runInBand",
1111
"clean": "rm -rf build dist tmp",
1212
"format": "prettier --write '**/*.ts'",
1313
"package": "ncc build --source-map --license licenses.txt"

src/Archiver.ts

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
import {existsSync} from 'fs';
2-
import {glob} from 'glob';
3-
import {basename, dirname, join} from 'path';
1+
import {basename, dirname} from 'path';
42
import {executeCommand} from './executeCommand';
53
import log, {LogLevel} from './log';
4+
import {locateArchiveFile} from './locateArchiveFile';
65

76
export interface ArtifactStore {
87
uploadArtifact(name: string, path: string): Promise<void>;
@@ -31,18 +30,7 @@ export default class Archiver {
3130
if (revision) archiveCommand += ` --revision ${revision}`;
3231
await executeCommand(archiveCommand);
3332

34-
const archiveFiles = (
35-
await glob(join('.appmap', 'archive', '**', '*.tar'), {dot: true})
36-
).filter(file => existsSync(file));
37-
38-
if (archiveFiles.length === 0) {
39-
throw new Error(`No AppMap archives found in ${process.cwd()}`);
40-
}
41-
if (archiveFiles.length > 1) {
42-
log(LogLevel.Warn, `Multiple AppMap archives found in ${process.cwd()}`);
43-
}
44-
45-
const archiveFile = archiveFiles.pop()!;
33+
const archiveFile = await locateArchiveFile('.');
4634

4735
log(LogLevel.Debug, `Processing AppMap archive ${archiveFile}`);
4836

src/executeCommand.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@ export function executeCommand(
2525
});
2626
}
2727
return new Promise<string>((resolve, reject) => {
28-
command.addListener('exit', code => {
29-
if (code === 0) {
28+
command.addListener('exit', (code, signal) => {
29+
if (signal || code === 0) {
30+
if (signal) log(LogLevel.Info, `Command killed by signal ${signal}`);
3031
resolve(result.join(''));
3132
} else {
3233
if (!printCommand) log(LogLevel.Warn, cmd);

src/locateArchiveFile.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import {existsSync} from 'fs';
2+
import {glob} from 'glob';
3+
import {join} from 'path';
4+
import log, {LogLevel} from './log';
5+
import {stat} from 'fs/promises';
6+
7+
export async function locateArchiveFile(workDir: string): Promise<string> {
8+
const archiveFiles = (
9+
await glob(join(workDir, '.appmap', 'archive', '**', '*.tar'), {dot: true})
10+
).filter(file => existsSync(file));
11+
const archiveFileTimes = new Map<string, number>();
12+
await Promise.all(
13+
archiveFiles.map(async file => archiveFileTimes.set(file, (await stat(file)).mtimeMs))
14+
);
15+
archiveFiles.sort((a, b) => archiveFileTimes.get(b)! - archiveFileTimes.get(a)!);
16+
17+
if (archiveFiles.length === 0)
18+
throw new Error(`No AppMap archives found in ${join(process.cwd(), workDir)}`);
19+
20+
const result = archiveFiles.shift()!;
21+
22+
if (archiveFiles.length > 1) {
23+
log(
24+
LogLevel.Warn,
25+
`Multiple AppMap archives found in ${join(
26+
process.cwd(),
27+
workDir
28+
)}.\nI'll upload the most recent one, which is ${result}.`
29+
);
30+
}
31+
32+
return result;
33+
}

test/helper.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import {join} from 'path';
2+
import verbose from '../src/verbose';
3+
import {mkdtempSync} from 'fs';
4+
5+
export const pwd = process.cwd();
6+
export const fixtureDir = join(__dirname, 'fixture');
7+
8+
export function makeWorkDir(): string {
9+
return mkdtempSync(join(__dirname, 'work', 'archive-appmap-action-'));
10+
}
11+
12+
if (process.env.VERBOSE) verbose(true);

test/locateArchiveFile.spec.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import {cp, mkdir, rm, writeFile} from 'fs/promises';
2+
import {locateArchiveFile} from '../src/locateArchiveFile';
3+
import * as test from './helper';
4+
import {join} from 'path';
5+
6+
const wait = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
7+
8+
describe('locateArchiveFile', () => {
9+
let workDir: string;
10+
11+
beforeEach(() => (workDir = test.makeWorkDir()));
12+
beforeEach(() => cp(test.fixtureDir, workDir, {recursive: true, force: true}));
13+
afterEach(() => rm(workDir, {recursive: true, force: true}));
14+
15+
it(`errors if there's no archive`, async () => {
16+
expect(locateArchiveFile(workDir)).rejects.toThrow(/No AppMap archives found/);
17+
});
18+
it(`chooses the most recent`, async () => {
19+
await mkdir(join(workDir, '.appmap/archive/full'), {recursive: true});
20+
await writeFile(join(workDir, '.appmap/archive/full/1.tar'), '');
21+
wait(1);
22+
await writeFile(join(workDir, '.appmap/archive/full/2.tar'), '');
23+
wait(1);
24+
await writeFile(join(workDir, '.appmap/archive/full/3.tar'), '');
25+
wait(1);
26+
27+
expect(locateArchiveFile(workDir)).resolves.toMatch(/\.appmap\/archive\/full\/3\.tar$/);
28+
});
29+
});

test/smoke.spec.ts

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,8 @@
11
import {randomUUID} from 'crypto';
22
import Archiver, {ArtifactStore} from '../src/Archiver';
33
import {executeCommand} from '../src/executeCommand';
4-
import {cp, readFile, rm} from 'fs/promises';
5-
import {join} from 'path';
6-
import verbose from '../src/verbose';
7-
8-
const pwd = process.cwd();
9-
const fixtureDir = join(__dirname, 'fixture');
10-
const workDir = join(__dirname, 'work');
11-
12-
if (process.env.VERBOSE) verbose(true);
4+
import * as test from './helper';
5+
import {cp, rm} from 'fs/promises';
136

147
class MockArtifactStore implements ArtifactStore {
158
public artifacts = new Map<string, string>();
@@ -39,14 +32,17 @@ describe('archive-appmap-action', () => {
3932
await executeCommand(`git checkout ${currentBranch}`);
4033
await executeCommand(`git branch -D ${archiveBranch}`);
4134
};
35+
let workDir: string;
4236

4337
beforeEach(() => (artifactStore = new MockArtifactStore()));
44-
beforeEach(async () => cp(fixtureDir, workDir, {recursive: true, force: true}));
38+
beforeEach(() => (workDir = test.makeWorkDir()));
39+
beforeEach(() => cp(test.fixtureDir, workDir, {recursive: true, force: true}));
4540
beforeEach(() => process.chdir(workDir));
4641
beforeEach(checkoutBranch);
42+
4743
afterEach(cleanupBranch);
48-
afterEach(() => process.chdir(pwd));
49-
afterEach(async () => rm(workDir, {recursive: true, force: true}));
44+
afterEach(() => process.chdir(test.pwd));
45+
afterEach(() => rm(workDir, {recursive: true, force: true}));
5046

5147
it('build and store an AppMap archive', async () => {
5248
const archiver = new Archiver(artifactStore);

test/work/.keep

Whitespace-only changes.

0 commit comments

Comments
 (0)