Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 76 additions & 12 deletions actions/setup/js/check_workflow_timestamp_api.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -63,39 +63,40 @@ async function main() {
}

// Helper function to compute and compare frontmatter hashes
async function logFrontmatterHashComparison() {
// Returns: { match: boolean, storedHash: string, recomputedHash: string } or null on error
async function compareFrontmatterHashes() {
try {
// Fetch lock file content to extract stored hash
const lockFileContent = await getFileContent(github, owner, repo, lockFilePath, ref);
if (!lockFileContent) {
core.info("Unable to fetch lock file content for hash comparison");
return;
return null;
}

const storedHash = extractHashFromLockFile(lockFileContent);
if (!storedHash) {
core.info("No frontmatter hash found in lock file");
return;
return null;
}

// Compute hash using pure JavaScript implementation
// Create a GitHub file reader for fetching workflow files via API
const fileReader = createGitHubFileReader(github, owner, repo, ref);
const recomputedHash = await computeFrontmatterHash(workflowMdPath, { fileReader });

const match = storedHash === recomputedHash;

// Log hash comparison
core.info(`Frontmatter hash comparison:`);
core.info(` Lock file hash: ${storedHash}`);
core.info(` Recomputed hash: ${recomputedHash}`);
core.info(` Status: ${match ? "✅ Hashes match" : "⚠️ Hashes differ"}`);

if (storedHash === recomputedHash) {
core.info(` Status: ✅ Hashes match`);
} else {
core.info(` Status: ⚠️ Hashes differ`);
}
return { match, storedHash, recomputedHash };
} catch (error) {
const errorMessage = getErrorMessage(error);
core.info(`Could not compute frontmatter hash: ${errorMessage}`);
return null;
}
}

Expand Down Expand Up @@ -124,10 +125,13 @@ async function main() {
core.info(` Source last commit: ${workflowDate.toISOString()} (${workflowCommit.sha.substring(0, 7)})`);
core.info(` Lock last commit: ${lockDate.toISOString()} (${lockCommit.sha.substring(0, 7)})`);

const workflowTime = workflowDate.getTime();
const lockTime = lockDate.getTime();

// Check if workflow file is newer than lock file
if (workflowDate > lockDate) {
// Log frontmatter hash comparison only when timestamp check fails
await logFrontmatterHashComparison();
if (workflowTime > lockTime) {
// Clear case: workflow file is newer - needs recompilation
await compareFrontmatterHashes(); // Log for diagnostic purposes
const warningMessage = `Lock file '${lockFilePath}' is outdated! The workflow file '${workflowMdPath}' has been modified more recently. Run 'gh aw compile' to regenerate the lock file.`;

// Format timestamps and commits for display
Expand All @@ -152,9 +156,69 @@ async function main() {
// Fail the step to prevent workflow from running with outdated configuration
core.setFailed(warningMessage);
} else if (workflowCommit.sha === lockCommit.sha) {
// Same commit - definitely up to date
core.info("✅ Lock file is up to date (same commit)");
} else if (workflowTime === lockTime) {
// Timestamps are equal (coarse timestamp) but different commits
// Use frontmatter hash comparison to determine if recompilation is needed
core.info("Timestamps are equal - using frontmatter hash comparison");
const hashComparison = await compareFrontmatterHashes();

if (!hashComparison) {
// Could not compute hash - be conservative and assume it's ok
core.info("⚠️ Could not compare frontmatter hashes - assuming lock file is up to date");
core.info("✅ Lock file is up to date (timestamp check passed, hash comparison unavailable)");
} else if (hashComparison.match) {
// Hashes match - lock file is up to date
core.info("✅ Lock file is up to date (hashes match)");
} else {
// Hashes differ - lock file needs recompilation
const warningMessage = `Lock file '${lockFilePath}' is outdated! Frontmatter hash mismatch detected. Run 'gh aw compile' to regenerate the lock file.`;

// Format timestamps and commits for display
const workflowTimestamp = workflowDate.toISOString();
const lockTimestamp = lockDate.toISOString();

// Add summary to GitHub Step Summary
let summary = core.summary
.addRaw("### ⚠️ Workflow Lock File Warning\n\n")
.addRaw("**WARNING**: Lock file is outdated (frontmatter hash mismatch).\n\n")
.addRaw("**Files:**\n")
.addRaw(`- Source: \`${workflowMdPath}\`\n`)
.addRaw(` - Last commit: ${workflowTimestamp}\n`)
.addRaw(` - Commit SHA: [\`${workflowCommit.sha.substring(0, 7)}\`](https://github.com/${owner}/${repo}/commit/${workflowCommit.sha})\n`)
.addRaw(` - Frontmatter hash: \`${hashComparison.recomputedHash.substring(0, 12)}...\`\n`)
.addRaw(`- Lock: \`${lockFilePath}\`\n`)
.addRaw(` - Last commit: ${lockTimestamp}\n`)
.addRaw(` - Commit SHA: [\`${lockCommit.sha.substring(0, 7)}\`](https://github.com/${owner}/${repo}/commit/${lockCommit.sha})\n`)
.addRaw(` - Stored hash: \`${hashComparison.storedHash.substring(0, 12)}...\`\n\n`)
.addRaw("**Action Required:** Run `gh aw compile` to regenerate the lock file.\n\n");

await summary.write();

// Fail the step to prevent workflow from running with outdated configuration
core.setFailed(warningMessage);
}
} else {
core.info("✅ Lock file is up to date");
// Lock file is newer than workflow file
// This means the lock was recompiled after the .md file, so it's up to date
// We verify the hash for informational purposes but don't fail
core.info("Lock file is newer - verifying frontmatter hash for consistency");
const hashComparison = await compareFrontmatterHashes();

if (!hashComparison) {
// Could not compute hash
core.info("⚠️ Could not compare frontmatter hashes");
core.info("✅ Lock file is up to date (lock is newer than source)");
} else if (hashComparison.match) {
// Hashes match - perfect consistency
core.info("✅ Lock file is up to date (lock is newer and hashes match)");
} else {
// Hashes differ but lock is newer, so it's still considered up to date
// The .md file may have been edited after the lock was compiled
core.info("⚠️ Frontmatter hash mismatch detected, but lock file is newer than source");
core.info("✅ Lock file is up to date (lock was recompiled after source changes)");
}
}
}

Expand Down
Loading
Loading