@@ -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