Skip to content

Commit c91813c

Browse files
authored
Fix Conan timestamp mismatch (#529)
1 parent c6815c4 commit c91813c

File tree

4 files changed

+93
-14
lines changed

4 files changed

+93
-14
lines changed

tasks/JFrogConan/conanUtils.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
// eslint-disable-next-line @typescript-eslint/no-namespace
33
declare namespace conan_utils {
44
function getCliPartialsBuildDir(buildName: string, buildNumber: string): string;
5+
function initCliPartialsBuildDir(buildName: string, buildNumber: string): number;
56
}
67
export = conan_utils;

tasks/JFrogConan/conanUtils.js

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ function executeConanTask(commandArgs) {
2828

2929
let conanTaskId = generateConanTaskUUId();
3030
tl.debug('Conan Task Id: ' + conanTaskId);
31-
let buildTimestamp = Date.now();
3231

3332
let conanPath = null;
3433
try {
@@ -58,7 +57,7 @@ function executeConanTask(commandArgs) {
5857
let buildName = tl.getInput('buildName', true);
5958
let buildNumber = tl.getInput('buildNumber', true);
6059
try {
61-
initCliPartialsBuildDir(buildName, buildNumber);
60+
let buildTimestamp = initCliPartialsBuildDir(buildName, buildNumber);
6261
setConanTraceFileLocation(conanUserHome, conanTaskId);
6362
setArtifactsBuildInfoProperties(conanUserHome, buildName, buildNumber, buildTimestamp);
6463
} catch (err) {
@@ -387,14 +386,56 @@ function purgeConanRemotes() {
387386
* Creates the path of for partials build info and initializing the details file with Timestamp.
388387
* @param buildName (string) - The build name
389388
* @param buildNumber (string) - The build number
389+
* @returns {number} - The timestamp of the build in milliseconds.
390390
*/
391391
function initCliPartialsBuildDir(buildName, buildNumber) {
392392
let partialsBuildDir = join(getCliPartialsBuildDir(buildName, buildNumber), 'partials');
393+
let partialBuildDetailsFile = join(partialsBuildDir, 'details');
394+
395+
// If a build was initialized before this task, read the build timestamp from the existing build details.
396+
if (fs.pathExistsSync(partialBuildDetailsFile)) {
397+
let buildTimestamp = readTimestampFromBuildPartialDetailsFile(partialBuildDetailsFile);
398+
if (buildTimestamp) {
399+
tl.debug('Read timestamp "' + buildTimestamp + '" from partial build details at: ' + partialBuildDetailsFile);
400+
return buildTimestamp;
401+
}
402+
}
403+
// If a build was not initialized, create a new build details file.
404+
return createBuildDetailsPartial(partialsBuildDir, partialBuildDetailsFile);
405+
}
406+
407+
/**
408+
* Creates the partial details file with the current timestamp.
409+
* @param partialsBuildDir (string) - path to the build's partials directory.
410+
* @param buildDetailsFile (string) - path to the build's partial build details file.
411+
* @returns {number} - The timestamp of the build in milliseconds.
412+
*/
413+
function createBuildDetailsPartial(partialsBuildDir, buildDetailsFile) {
393414
if (!fs.pathExistsSync(partialsBuildDir)) {
394415
fs.ensureDirSync(partialsBuildDir);
395416
}
396-
fs.writeJsonSync(join(partialsBuildDir, 'details'), { Timestamp: new Date().toISOString() });
397-
tl.debug('Created partial details at: ' + join(partialsBuildDir, 'details'));
417+
418+
// The start time is saved as ISO, but the artifacts property is saved as a timestamp.
419+
let buildStartTime = new Date();
420+
fs.writeJsonSync(buildDetailsFile, { Timestamp: buildStartTime.toISOString() });
421+
tl.debug('Created partial build details at: ' + buildDetailsFile);
422+
return buildStartTime.getTime();
423+
}
424+
425+
/**
426+
* Reads the build start time from the build's partial build details file, and returns it as timestamp.
427+
* @param buildDetailsFile (string) - path to the build's partial build details file.
428+
* @returns {number} - The timestamp of the build in milliseconds.
429+
*/
430+
function readTimestampFromBuildPartialDetailsFile(buildDetailsFile) {
431+
try {
432+
const data = fs.readFileSync(buildDetailsFile, 'utf8');
433+
const jsonData = JSON.parse(data);
434+
return Date.parse(jsonData.Timestamp);
435+
} catch (err) {
436+
console.error('Error reading or parsing the build details partials file:', err);
437+
return undefined;
438+
}
398439
}
399440

400441
function getCliPartialsBuildDir(buildName, buildNumber) {
@@ -405,6 +446,8 @@ function getCliPartialsBuildDir(buildName, buildNumber) {
405446

406447
module.exports = {
407448
executeConanTask: executeConanTask,
408-
getCliPartialsBuildDir: getCliPartialsBuildDir, // Exported for tests
409449
purgeConanRemotes: purgeConanRemotes,
450+
// Exported for tests:
451+
getCliPartialsBuildDir: getCliPartialsBuildDir,
452+
initCliPartialsBuildDir: initCliPartialsBuildDir,
410453
};

tests/testUtils.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ const repoKeys: any = {
3939
pipRemoteRepo: 'pip-remote',
4040
pipVirtualRepo: 'pip-virtual',
4141
releaseBundlesRepo: 'rb-repo',
42-
dockerLocalRepo: 'docker-local'
42+
dockerLocalRepo: 'docker-local',
4343
};
4444

4545
export { testDataDir, repoKeys, platformUrl, platformPassword, platformUsername, platformAccessToken, platformDockerDomain };
@@ -165,7 +165,7 @@ export function createTestRepositories(): void {
165165
url: 'https://releases.jfrog.io/artifactory/jfrog-cli/v2-jf',
166166
}),
167167
);
168-
if (!isSkipTest('maven')) {
168+
if (!isSkipTest('maven')) {
169169
createRepo(repoKeys.mavenLocalRepo, JSON.stringify({ rclass: 'local', packageType: 'maven' }));
170170
createRepo(
171171
repoKeys.mavenRemoteRepo,
@@ -176,7 +176,7 @@ export function createTestRepositories(): void {
176176
}),
177177
);
178178
}
179-
if (!isSkipTest('nuget') && !isSkipTest('dotnet')) {
179+
if (!isSkipTest('nuget') && !isSkipTest('dotnet')) {
180180
createRepo(
181181
repoKeys.nugetLocalRepo,
182182
JSON.stringify({
@@ -207,7 +207,7 @@ export function createTestRepositories(): void {
207207
}),
208208
);
209209
}
210-
if (!isSkipTest('npm')) {
210+
if (!isSkipTest('npm')) {
211211
createRepo(
212212
repoKeys.npmLocalRepo,
213213
JSON.stringify({
@@ -235,10 +235,10 @@ export function createTestRepositories(): void {
235235
}),
236236
);
237237
}
238-
if (!isSkipTest('conan')) {
238+
if (!isSkipTest('conan')) {
239239
createRepo(repoKeys.conanLocalRepo, JSON.stringify({ rclass: 'local', packageType: 'conan' }));
240240
}
241-
if (!isSkipTest('go')) {
241+
if (!isSkipTest('go')) {
242242
createRepo(
243243
repoKeys.goLocalRepo,
244244
JSON.stringify({
@@ -266,7 +266,7 @@ export function createTestRepositories(): void {
266266
}),
267267
);
268268
}
269-
if (!isSkipTest('pip')) {
269+
if (!isSkipTest('pip')) {
270270
createRepo(repoKeys.pipLocalRepo, JSON.stringify({ rclass: 'local', packageType: 'pypi', repoLayoutRef: 'simple-default' }));
271271
createRepo(
272272
repoKeys.pipRemoteRepo,
@@ -293,7 +293,7 @@ export function createTestRepositories(): void {
293293
packageType: 'docker',
294294
dockerApiVersion: 'V2',
295295
dockerV1Enabled: false,
296-
enableTokenAuthentication: true
296+
enableTokenAuthentication: true,
297297
}),
298298
);
299299
}

tests/tests.ts

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,14 @@ describe('JFrog Artifactory Extension Tests', (): void => {
219219
},
220220
TestUtils.isSkipTest('unit'),
221221
);
222+
223+
runSyncTest(
224+
'Conan Utils - Init build details partial and verify consistency in timestamp',
225+
(): void => {
226+
testInitCliPartialsBuildDir();
227+
},
228+
TestUtils.isSkipTest('unit'),
229+
);
222230
});
223231

224232
describe('JFrog CLI Task Tests', (): void => {
@@ -745,7 +753,9 @@ describe('JFrog Artifactory Extension Tests', (): void => {
745753
const filesDir: string = TestUtils.isWindows() ? 'windowsFiles' : 'unixFiles';
746754

747755
// Run docker build + tag
748-
execSync(`docker build -t ${platformDockerDomain}/${repoKeys.dockerLocalRepo}/docker-test:1 ${join(__dirname, 'resources', testDir, filesDir)}`);
756+
execSync(
757+
`docker build -t ${platformDockerDomain}/${repoKeys.dockerLocalRepo}/docker-test:1 ${join(__dirname, 'resources', testDir, filesDir)}`,
758+
);
749759

750760
// run docker push
751761
mockTask(testDir, 'push');
@@ -1227,6 +1237,31 @@ function testGetCliPartialsBuildDir(): void {
12271237
testDTO.testsBuildNames.forEach((element: string): void => runBuildCommand('bc', element, testDTO.testBuildNumber));
12281238
}
12291239

1240+
function testInitCliPartialsBuildDir(): void {
1241+
const testsBuildName: string = 'partialTestBuildName';
1242+
const testBuildNumber: string = '123';
1243+
1244+
// Cleanup old partials.
1245+
runBuildCommand('bc', testsBuildName, testBuildNumber);
1246+
1247+
// Init build partials directory. A new build timestamp should be generated.
1248+
let originalBuildTimestamp: number = conanUtils.initCliPartialsBuildDir(testsBuildName, testBuildNumber);
1249+
assert.ok(originalBuildTimestamp, 'A timestamp should have been generated');
1250+
assert.equal(originalBuildTimestamp.toString().length, 13, 'The timestamp should be valid');
1251+
1252+
// Calling initialization again. Since it already exists, we expect the same timestamp to be returned.
1253+
let newBuildTimestamp: number = conanUtils.initCliPartialsBuildDir(testsBuildName, testBuildNumber);
1254+
assert.equal(originalBuildTimestamp, newBuildTimestamp, 'The timestamp should not have changed');
1255+
1256+
// Cleanup existing partials, init again and assert the new timestamp.
1257+
runBuildCommand('bc', testsBuildName, testBuildNumber);
1258+
newBuildTimestamp = conanUtils.initCliPartialsBuildDir(testsBuildName, testBuildNumber);
1259+
assert.notEqual(originalBuildTimestamp, newBuildTimestamp, 'The timestamp should have changed');
1260+
1261+
// Cleanup test.
1262+
runBuildCommand('bc', testsBuildName, testBuildNumber);
1263+
}
1264+
12301265
function runBuildCommand(command: string, buildName: string, buildNumber: string): void {
12311266
jfrogUtils.executeCliCommand('jf rt ' + command + ' "' + buildName + '" ' + buildNumber, TestUtils.testDataDir);
12321267
}

0 commit comments

Comments
 (0)