From 560362916123a8bfa8727defaf06b8135608346d Mon Sep 17 00:00:00 2001 From: Kevin Hanselman Date: Sat, 29 Jun 2024 18:32:00 +0000 Subject: [PATCH] Add more explanation to dud run output (#209) fixes #100, fixes #162 --- go.mod | 30 +++++------ go.sum | 60 +++++++++++----------- src/index/run.go | 43 ++++++++++++---- src/index/run_test.go | 116 ++++++++++++++++++++++++++++++++++-------- src/stage/stage.go | 1 + 5 files changed, 174 insertions(+), 76 deletions(-) diff --git a/go.mod b/go.mod index f2c0bfa..ed03a70 100644 --- a/go.mod +++ b/go.mod @@ -11,45 +11,45 @@ require ( github.com/mattn/go-isatty v0.0.20 github.com/mitchellh/go-homedir v1.1.0 github.com/pkg/errors v0.9.1 - github.com/spf13/cobra v1.8.0 - github.com/spf13/viper v1.18.2 - github.com/stretchr/testify v1.8.4 + github.com/spf13/cobra v1.8.1 + github.com/spf13/viper v1.19.0 + github.com/stretchr/testify v1.9.0 github.com/zeebo/blake3 v0.2.3 go.uber.org/goleak v1.3.0 - golang.org/x/sync v0.6.0 + golang.org/x/sync v0.7.0 gopkg.in/yaml.v2 v2.4.0 ) require ( github.com/VividCortex/ewma v1.2.0 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/google/pprof v0.0.0-20231229205709-960ae82b1e42 // indirect + github.com/google/pprof v0.0.0-20240625030939-27f56978b8b0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/klauspost/cpuid/v2 v2.2.6 // indirect + github.com/klauspost/cpuid/v2 v2.2.8 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/pelletier/go-toml/v2 v2.1.1 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/rivo/uniseg v0.4.4 // indirect + github.com/rivo/uniseg v0.4.7 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/locafero v0.6.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/stretchr/objx v0.5.1 // indirect + github.com/stretchr/objx v0.5.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc // indirect - golang.org/x/sys v0.16.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect + golang.org/x/sys v0.21.0 // indirect + golang.org/x/text v0.16.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 6c5d329..c60972d 100644 --- a/go.sum +++ b/go.sum @@ -9,14 +9,14 @@ github.com/cheggaaa/pb/v3 v3.1.5/go.mod h1:CrxkeghYTXi1lQBEI7jSn+3svI3cuc19haAj6 github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= -github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= @@ -25,16 +25,16 @@ github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyT github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= -github.com/google/pprof v0.0.0-20231229205709-960ae82b1e42 h1:dHLYa5D8/Ta0aLR2XcPsrkpAgGeFs6thhMcQK0oQ0n8= -github.com/google/pprof v0.0.0-20231229205709-960ae82b1e42/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= +github.com/google/pprof v0.0.0-20240625030939-27f56978b8b0 h1:e+8XbKB6IMn8A4OAyZccO4pYfB3s7bt6azNIPE7AnPg= +github.com/google/pprof v0.0.0-20240625030939-27f56978b8b0/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= -github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= -github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= +github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -50,21 +50,21 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI= -github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= -github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/locafero v0.6.0 h1:ON7AQg37yzcRPU69mt7gwhFEBwxI6P9T4Qu3N51bwOk= +github.com/sagikazarmark/locafero v0.6.0/go.mod h1:77OmuIc6VTraTXKXIs/uvUxKGUXjE1GbemJYHqdNjX0= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= @@ -73,22 +73,22 @@ github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= -github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= -github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= +github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.1 h1:4VhoImhV/Bm0ToFkXFi8hXNXwpDRZ/ynw3amt82mzq0= -github.com/stretchr/objx v0.5.1/go.mod h1:/iHQpkQwBD6DLUmQ4pE+s1TXdob1mORJ4/UFdrifcy0= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY= @@ -101,18 +101,18 @@ go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc h1:ao2WRsKSzW6KuUY9IWPwWahcHCgR0s52IfwutMfEbdM= -golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY= +golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= diff --git a/src/index/run.go b/src/index/run.go index 74c2a74..50bb3f4 100644 --- a/src/index/run.go +++ b/src/index/run.go @@ -48,12 +48,22 @@ func (idx Index) Run( checksumUpToDate = realChecksum == stg.Checksum } + doRun := false + var runReason string + // Run if we have a command and no inputs. - doRun := hasCommand && (len(stg.Inputs) == 0) + if hasCommand && (len(stg.Inputs) == 0) { + doRun = true + runReason = "has command and no inputs" + } // Run if our checksum is stale. - doRun = doRun || !checksumUpToDate + if !checksumUpToDate { + doRun = true + runReason = "definition modified" + } + // Always check all upstream stages. for artPath, art := range stg.Inputs { ownerPath, _ := idx.findOwner(artPath) if ownerPath == "" { @@ -61,14 +71,21 @@ func (idx Index) Run( if err != nil { return err } - doRun = doRun || !artStatus.ContentsMatch + if !artStatus.ContentsMatch { + doRun = true + runReason = "input out-of-date" + } } else if recursive { if err := idx.Run(ownerPath, ch, rootDir, recursive, ran, inProgress, logger); err != nil { return err } - doRun = doRun || ran[ownerPath] + if ran[ownerPath] { + doRun = true + runReason = "upstream stage out-of-date" + } } } + if !doRun { for _, art := range stg.Outputs { artStatus, err := ch.Status(rootDir, *art, true) @@ -77,17 +94,25 @@ func (idx Index) Run( } if !artStatus.ContentsMatch { doRun = true + runReason = "output out-of-date" break } } } - if doRun && hasCommand { - logger.Info.Printf("running stage %s\n", stagePath) - if err := runCommand(stg.CreateCommand()); err != nil { - return err + if doRun { + if hasCommand { + logger.Info.Printf("running stage %s (%s)\n", stagePath, runReason) + cmd := stg.CreateCommand() + // Avoid cmd.Command here because it will include "sh -c ...". + logger.Debug.Printf("(in %s) %s\n", cmd.Dir, stg.Command) + if err := runCommand(cmd); err != nil { + return err + } + } else { + logger.Info.Printf("nothing to do for stage %s (%s, but no command)\n", stagePath, runReason) } } else { - logger.Info.Printf("nothing to do for stage %s\n", stagePath) + logger.Info.Printf("nothing to do for stage %s (up-to-date)\n", stagePath) } ran[stagePath] = doRun delete(inProgress, stagePath) diff --git a/src/index/run_test.go b/src/index/run_test.go index be50fb9..186540e 100644 --- a/src/index/run_test.go +++ b/src/index/run_test.go @@ -1,8 +1,10 @@ package index import ( + "log" "os/exec" "path/filepath" + "strings" "testing" "github.com/google/go-cmp/cmp" @@ -49,9 +51,6 @@ func TestRun(t *testing.T) { rootDir := "project/root" var commands map[string]*exec.Cmd - resetRunCommandMock := func() { - commands = make(map[string]*exec.Cmd) - } runCommandOrig := runCommand runCommand = func(cmd *exec.Cmd) error { lastArg := cmd.Args[len(cmd.Args)-1] @@ -68,11 +67,17 @@ func TestRun(t *testing.T) { } } - // TODO: Consider checking the logs instead of throwing them away. + var infoLog strings.Builder logger := agglog.NewNullLogger() + resetTestHarness := func() { + commands = make(map[string]*exec.Cmd) + infoLog = strings.Builder{} + logger.Info = log.New(&infoLog, "", 0) + } + t.Run("up-to-date stage without command doesn't suggest run", func(t *testing.T) { - defer resetRunCommandMock() + resetTestHarness() stgA := stage.Stage{ WorkingDir: "a", Outputs: map[string]*artifact.Artifact{ @@ -104,10 +109,15 @@ func TestRun(t *testing.T) { if diff := cmp.Diff(expectedRan, ran); diff != "" { t.Fatalf("committed -want +got:\n%s", diff) } + + wantLog := "nothing to do for stage foo.yaml (up-to-date)\n" + if diff := cmp.Diff(wantLog, infoLog.String()); diff != "" { + t.Fatalf("log -want +got:\n%s", diff) + } }) t.Run("out-of-date stage without command does suggest run", func(t *testing.T) { - defer resetRunCommandMock() + resetTestHarness() stgA := stage.Stage{ WorkingDir: "a", Outputs: map[string]*artifact.Artifact{ @@ -118,7 +128,6 @@ func TestRun(t *testing.T) { idx := Index{"foo.yaml": &stgA} mockCache := mocks.Cache{} - expectStageStatusCalled(&stgA, &mockCache, rootDir, outOfDate(), true) ran := make(map[string]bool) @@ -139,10 +148,15 @@ func TestRun(t *testing.T) { if diff := cmp.Diff(expectedRan, ran); diff != "" { t.Fatalf("committed -want +got:\n%s", diff) } + + wantLog := "nothing to do for stage foo.yaml (output out-of-date, but no command)\n" + if diff := cmp.Diff(wantLog, infoLog.String()); diff != "" { + t.Fatalf("log -want +got:\n%s", diff) + } }) t.Run("stage with command and no inputs always runs (outputs up-to-date)", func(t *testing.T) { - defer resetRunCommandMock() + resetTestHarness() stgA := stage.Stage{ Command: "echo 'Running Stage A'", WorkingDir: "a", @@ -175,25 +189,29 @@ func TestRun(t *testing.T) { if diff := cmp.Diff(expectedRan, ran); diff != "" { t.Fatalf("committed -want +got:\n%s", diff) } + + wantLog := "running stage foo.yaml (has command and no inputs)\n" + if diff := cmp.Diff(wantLog, infoLog.String()); diff != "" { + t.Fatalf("log -want +got:\n%s", diff) + } }) t.Run("stage with command and no inputs always runs (outputs out-of-date)", func(t *testing.T) { - defer resetRunCommandMock() - stgA := stage.Stage{ + resetTestHarness() + stg := stage.Stage{ Command: "echo 'Running Stage A'", WorkingDir: "a", Outputs: map[string]*artifact.Artifact{ "foo.bin": {Path: "foo.bin"}, }, } + updateChecksum(&stg, t) idx := Index{ - "foo.yaml": &stgA, + "foo.yaml": &stg, } mockCache := mocks.Cache{} - expectStageStatusCalled(&stgA, &mockCache, rootDir, outOfDate(), true) - ran := make(map[string]bool) inProgress := make(map[string]bool) if err := idx.Run("foo.yaml", &mockCache, rootDir, true, ran, inProgress, logger); err != nil { @@ -204,7 +222,7 @@ func TestRun(t *testing.T) { t.Fatalf("runCommand called %d time(s), want 1", len(commands)) } - assertCorrectCommand(stgA, commands, t) + assertCorrectCommand(stg, commands, t) expectedRan := map[string]bool{ "foo.yaml": true, @@ -212,10 +230,15 @@ func TestRun(t *testing.T) { if diff := cmp.Diff(expectedRan, ran); diff != "" { t.Fatalf("committed -want +got:\n%s", diff) } + + wantLog := "running stage foo.yaml (has command and no inputs)\n" + if diff := cmp.Diff(wantLog, infoLog.String()); diff != "" { + t.Fatalf("log -want +got:\n%s", diff) + } }) t.Run("two stages, both up-to-date", func(t *testing.T) { - defer resetRunCommandMock() + resetTestHarness() stgA := stage.Stage{ Outputs: map[string]*artifact.Artifact{ "foo.bin": {Path: "foo.bin"}, @@ -261,10 +284,16 @@ func TestRun(t *testing.T) { if diff := cmp.Diff(expectedRan, ran); diff != "" { t.Fatalf("committed -want +got:\n%s", diff) } + + wantLog := "nothing to do for stage foo.yaml (up-to-date)\n" + + "nothing to do for stage bar.yaml (up-to-date)\n" + if diff := cmp.Diff(wantLog, infoLog.String()); diff != "" { + t.Fatalf("log -want +got:\n%s", diff) + } }) t.Run("two stages, upstream out-of-date", func(t *testing.T) { - defer resetRunCommandMock() + resetTestHarness() stgA := stage.Stage{ Outputs: map[string]*artifact.Artifact{ "foo.bin": {Path: "foo.bin"}, @@ -313,10 +342,16 @@ func TestRun(t *testing.T) { if diff := cmp.Diff(expectedRan, ran); diff != "" { t.Fatalf("committed -want +got:\n%s", diff) } + + wantLog := "nothing to do for stage foo.yaml (output out-of-date, but no command)\n" + + "running stage bar.yaml (upstream stage out-of-date)\n" + if diff := cmp.Diff(wantLog, infoLog.String()); diff != "" { + t.Fatalf("log -want +got:\n%s", diff) + } }) t.Run("two stages, downstream out-of-date", func(t *testing.T) { - defer resetRunCommandMock() + resetTestHarness() stgA := stage.Stage{ Outputs: map[string]*artifact.Artifact{ "foo.bin": {Path: "foo.bin"}, @@ -364,10 +399,16 @@ func TestRun(t *testing.T) { if diff := cmp.Diff(expectedRan, ran); diff != "" { t.Fatalf("committed -want +got:\n%s", diff) } + + wantLog := "nothing to do for stage foo.yaml (up-to-date)\n" + + "running stage bar.yaml (output out-of-date)\n" + if diff := cmp.Diff(wantLog, infoLog.String()); diff != "" { + t.Fatalf("log -want +got:\n%s", diff) + } }) t.Run("ensure all inputs are checked", func(t *testing.T) { - defer resetRunCommandMock() + resetTestHarness() inA := stage.Stage{ Outputs: map[string]*artifact.Artifact{ "bish.bin": {Path: "bish.bin"}, @@ -424,10 +465,25 @@ func TestRun(t *testing.T) { if diff := cmp.Diff(expectedRan, ran); diff != "" { t.Fatalf("committed -want +got:\n%s", diff) } + + gotLogs := make(map[string]bool) + for _, line := range strings.Split(infoLog.String(), "\n") { + if len(line) > 0 { + gotLogs[line] = true + } + } + wantLogs := map[string]bool{ + "nothing to do for stage bish.yaml (output out-of-date, but no command)": true, + "nothing to do for stage bash.yaml (up-to-date)": true, + "running stage bosh.yaml (upstream stage out-of-date)": true, + } + if diff := cmp.Diff(wantLogs, gotLogs); diff != "" { + t.Fatalf("log -want +got:\n%s", diff) + } }) t.Run("cycles are prevented", func(t *testing.T) { - defer resetRunCommandMock() + resetTestHarness() // stgA <-- stgB <-- stgC --> stgD // |---------------^ stgA := stage.Stage{ @@ -496,7 +552,7 @@ func TestRun(t *testing.T) { }) t.Run("run when any orphan input is out-of-date", func(t *testing.T) { - defer resetRunCommandMock() + resetTestHarness() bish := upToDate() bish.Artifact = artifact.Artifact{Path: "bish.bin"} @@ -542,10 +598,15 @@ func TestRun(t *testing.T) { if diff := cmp.Diff(expectedRan, ran); diff != "" { t.Fatalf("committed -want +got:\n%s", diff) } + + wantLog := "running stage bosh.yaml (input out-of-date)\n" + if diff := cmp.Diff(wantLog, infoLog.String()); diff != "" { + t.Fatalf("log -want +got:\n%s", diff) + } }) t.Run("can disable recursion", func(t *testing.T) { - defer resetRunCommandMock() + resetTestHarness() stgA := stage.Stage{ Outputs: map[string]*artifact.Artifact{ "foo.bin": {Path: "foo.bin"}, @@ -590,10 +651,15 @@ func TestRun(t *testing.T) { if diff := cmp.Diff(expectedRan, ran); diff != "" { t.Fatalf("committed -want +got:\n%s", diff) } + + wantLog := "running stage bar.yaml (output out-of-date)\n" + if diff := cmp.Diff(wantLog, infoLog.String()); diff != "" { + t.Fatalf("log -want +got:\n%s", diff) + } }) t.Run("stage with out-of-date definition does run", func(t *testing.T) { - defer resetRunCommandMock() + resetTestHarness() stgA := stage.Stage{ Outputs: map[string]*artifact.Artifact{ "foo.bin": {Path: "foo.bin"}, @@ -639,5 +705,11 @@ func TestRun(t *testing.T) { if diff := cmp.Diff(expectedRan, ran); diff != "" { t.Fatalf("committed -want +got:\n%s", diff) } + + wantLog := "nothing to do for stage foo.yaml (up-to-date)\n" + + "running stage bar.yaml (definition modified)\n" + if diff := cmp.Diff(wantLog, infoLog.String()); diff != "" { + t.Fatalf("log -want +got:\n%s", diff) + } }) } diff --git a/src/stage/stage.go b/src/stage/stage.go index b9dbde6..0c9e36d 100644 --- a/src/stage/stage.go +++ b/src/stage/stage.go @@ -148,6 +148,7 @@ func FromFile(stagePath string) (stg Stage, err error) { // If stagePath is not empty, Artifacts matching stagePath will cause an error; // stages cannot track or reference themselves. func (stg Stage) Validate(stagePath string) error { + // TODO: Resolve paths instead of a string check. if strings.Contains(stg.WorkingDir, "..") { return fmt.Errorf("working directory %s is outside of the project root", stg.WorkingDir) }