Skip to content

Commit 0653f68

Browse files
committed
feat: enhance deptrac image generation with change detection
1 parent 57d3cef commit 0653f68

File tree

1 file changed

+50
-7
lines changed

1 file changed

+50
-7
lines changed

booster/.husky/shared/extras.ts

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,36 @@ export interface ArtifactResult {
1010
path?: string
1111
}
1212

13+
/**
14+
* Check if deptrac.png was freshly written and whether it differs from git HEAD.
15+
*
16+
* @param mtimeBefore - mtime of the file before deptrac ran (0 if it didn't exist)
17+
* @returns ArtifactResult with generated=true if freshly written, changed=true if content differs from git
18+
*/
19+
async function checkDeptracImage(mtimeBefore: number): Promise<ArtifactResult> {
20+
if (!(await fs.pathExists('./deptrac.png'))) {
21+
return { generated: false, changed: false }
22+
}
23+
24+
const mtimeAfter = (await fs.stat('./deptrac.png')).mtimeMs
25+
if (mtimeAfter <= mtimeBefore) {
26+
// File was not rewritten during this run — stale from a previous run
27+
return { generated: false, changed: false }
28+
}
29+
30+
// File was freshly generated. Check if content differs from what's in git.
31+
try {
32+
const diffResult = await exec(['git', 'diff', '--name-only', '--', 'deptrac.png'], {
33+
quiet: true,
34+
})
35+
const changed = diffResult.toString().trim().includes('deptrac.png')
36+
return { generated: true, changed, path: 'deptrac.png' }
37+
} catch {
38+
// git diff can fail if the file is untracked; treat as changed
39+
return { generated: true, changed: true, path: 'deptrac.png' }
40+
}
41+
}
42+
1343
/**
1444
* Generate Deptrac architecture diagram
1545
*
@@ -23,21 +53,34 @@ export async function generateDeptracImage(): Promise<ArtifactResult> {
2353
return { generated: false, changed: false }
2454
}
2555

26-
try {
27-
log.tool('Deptrac', 'Generating architecture diagram...')
56+
log.tool('Deptrac', 'Generating architecture diagram...')
57+
58+
// Capture mtime before running so we can detect if the file was (re)written
59+
const mtimeBefore = (await fs.pathExists('./deptrac.png'))
60+
? (await fs.stat('./deptrac.png')).mtimeMs
61+
: 0
2862

63+
try {
2964
await exec(
3065
['./vendor/bin/deptrac', '--formatter=graphviz-image', '--output=deptrac.png'],
3166
{ type: 'php' },
3267
)
3368

34-
if (await fs.pathExists('./deptrac.png')) {
35-
log.success('Deptrac image generated: deptrac.png')
36-
return { generated: true, changed: true, path: 'deptrac.png' }
69+
const result = await checkDeptracImage(mtimeBefore)
70+
if (result.generated) {
71+
log.success(`Deptrac image generated${result.changed ? '' : ' (unchanged)'}: deptrac.png`)
3772
}
38-
39-
return { generated: false, changed: false }
73+
return result
4074
} catch (error: unknown) {
75+
// Deptrac exits with code 1 when violations are found, but still generates the image.
76+
// Check if the file was freshly written despite the non-zero exit.
77+
const result = await checkDeptracImage(mtimeBefore)
78+
if (result.generated) {
79+
const status = result.changed ? '' : ' (unchanged)'
80+
log.success(`Deptrac image generated (violations found)${status}: deptrac.png`)
81+
return result
82+
}
83+
4184
const errorMessage = error instanceof Error ? error.message : String(error)
4285
log.warn(`Deptrac image generation failed: ${errorMessage}`)
4386
return { generated: false, changed: false }

0 commit comments

Comments
 (0)