11name : Integration Tests
22
3- # Only run workflow manually
4- # Refer to https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows#workflow_dispatch
53on :
64 push :
75 workflow_dispatch :
86 schedule :
97 - cron : " 0 5 * * *" # At 05:00 on every day.
108
9+ # Cancel in-progress runs for the same branch so stale runs don't block the runner.
10+ concurrency :
11+ group : integration-${{ github.ref }}
12+ cancel-in-progress : true
13+
14+ # All match patterns for integration test groups. Each group runs a subset;
15+ # the build job validates that every test belongs to exactly one group.
16+ env :
17+ TEST_GROUPS : >-
18+ Analysis.Maven Analysis.Gradle Analysis.Scala Analysis.Clojure
19+ Analysis.Go Analysis.Rust Analysis.Erlang Analysis.Elixir
20+ Analysis.Python Analysis.Ruby Analysis.Swift Analysis.Cocoapods
21+ Analysis.Pnpm Analysis.Nuget Analysis.Carthage Analysis.LicenseScanner
22+ Container.Analysis Reachability.Upload
23+
1124jobs :
12- integration-test :
13- name : integration-test
25+ # Build once, then run test groups in parallel.
26+ # The build job populates the cabal and dist-newstyle caches.
27+ # Each test job restores those caches so it doesn't need to rebuild.
28+ build :
29+ name : build
1430 runs-on : " fossa-cli-integration-runner"
15- # Be sure to update the env below too
1631 container : fossa/haskell-static-alpine:ghc-9.8.4
17-
32+ outputs :
33+ latest-tag : ${{ steps.latest-tag.outputs.tag }}
1834 env :
1935 GHC_VERSION : ' 9.8.4'
2036
@@ -29,13 +45,11 @@ jobs:
2945
3046 - name : Get latest release tag
3147 id : latest-tag
32- run : echo "tag=$(git describe --tags --abbrev=0 2>/dev/null || echo none)" >> $GITHUB_OUTPUT
48+ run : echo "tag=$(git tag --sort=-v:refname | head -1 2>/dev/null || echo none)" >> $GITHUB_OUTPUT
3349
3450 - name : Ensures git ownership check does not lead to compile error (we run git during compile for version tagging, etc.)
3551 run : git config --global --add safe.directory "$GITHUB_WORKSPACE"
3652
37- # adduser cannot add users to group: https://unix.stackexchange.com/a/397733
38- # so we edit /etc/group directly
3953 - name : Create nixbuild users/group
4054 run : |
4155 addgroup nixbld
@@ -60,19 +74,15 @@ jobs:
6074
6175 - uses : Swatinem/rust-cache@v2
6276
63- # Cache cabal store and dist-newstyle keyed on spectrometer.cabal + project file.
64- # cabal build handles staleness internally — if a transitive dep changed,
65- # it recompiles only what's needed. This avoids the 8-min cabal update +
66- # dry-run solver step that the plan-hash approach requires.
67- - uses : actions/cache@v4
77+ - uses : actions/cache@v5
6878 name : Cache cabal store
6979 with :
7080 path : ${{ steps.setup-haskell.outputs.cabal-store || '~/.local/state/cabal' }}
7181 key : ${{ runner.os }}-${{ env.GHC_VERSION }}-cabal-cache-${{ hashFiles('spectrometer.cabal', 'cabal.project.ci.linux', 'cabal.project.common') }}
7282 restore-keys : |
7383 ${{ runner.os }}-${{ env.GHC_VERSION }}-cabal-cache-
7484
75- - uses : actions/cache@v4
85+ - uses : actions/cache@v5
7686 name : Cache dist-newstyle
7787 with :
7888 path : ${{ github.workspace }}/dist-newstyle
@@ -98,8 +108,132 @@ jobs:
98108 cabal update
99109 $RUN_CMD || $RUN_CMD
100110
101- # This is set up to run integration tests in parallel.
102- # If that becomes a problem disable it by removing the "+RTS -N -RTS" test options.
103- - name : Run all integration tests
111+ # Verify every integration test is covered by at least one group pattern.
112+ # Counts tests from an unfiltered --dry-run vs the union of all --match
113+ # patterns. Fails if any tests would be silently skipped.
114+ - name : Validate test groups cover all tests
104115 run : |
105- cabal test --project-file=cabal.project.ci.linux --test-show-details=direct --test-option=--times integration-tests --test-options="+RTS -N -RTS"
116+ TOTAL=$(cabal test --project-file=cabal.project.ci.linux \
117+ --test-show-details=direct \
118+ integration-tests \
119+ --test-option=--dry-run 2>&1 | grep -c "^ " || echo 0)
120+
121+ MATCH_ARGS=""
122+ for pattern in $TEST_GROUPS; do
123+ MATCH_ARGS="$MATCH_ARGS --test-option=--match --test-option=$pattern"
124+ done
125+ MATCHED=$(cabal test --project-file=cabal.project.ci.linux \
126+ --test-show-details=direct \
127+ $MATCH_ARGS \
128+ integration-tests \
129+ --test-option=--dry-run 2>&1 | grep -c "^ " || echo 0)
130+
131+ echo "Total tests: $TOTAL"
132+ echo "Matched tests: $MATCHED"
133+ if [ "$TOTAL" -ne "$MATCHED" ]; then
134+ echo "ERROR: $((TOTAL - MATCHED)) integration tests are not covered by any group pattern."
135+ echo "Update TEST_GROUPS in integrations-test.yml to include the missing patterns."
136+ exit 1
137+ fi
138+
139+ # Upload artifacts that test jobs need so they don't have to rebuild
140+ # Rust or re-download vendor binaries.
141+ - uses : actions/upload-artifact@v4
142+ with :
143+ name : vendor-bins
144+ path : vendor-bins/
145+
146+ - uses : actions/upload-artifact@v4
147+ with :
148+ name : rust-release-bins
149+ path : |
150+ target/release/berkeleydb
151+ target/release/millhone
152+
153+ integration-test :
154+ name : test-${{ matrix.group }}
155+ needs : build
156+ runs-on : " fossa-cli-integration-runner"
157+ container : fossa/haskell-static-alpine:ghc-9.8.4
158+ env :
159+ GHC_VERSION : ' 9.8.4'
160+
161+ strategy :
162+ fail-fast : false
163+ matrix :
164+ include :
165+ - group : jvm
166+ matches : " Analysis.Maven Analysis.Gradle Analysis.Scala Analysis.Clojure"
167+
168+ - group : compiled
169+ matches : " Analysis.Go Analysis.Rust Analysis.Erlang Analysis.Elixir"
170+
171+ - group : scripting-and-other
172+ matches : " Analysis.Python Analysis.Ruby Analysis.Swift Analysis.Cocoapods Analysis.Pnpm Analysis.Nuget Analysis.Carthage Analysis.LicenseScanner Container.Analysis Reachability.Upload"
173+
174+ steps :
175+ - uses : actions/checkout@v4
176+ with :
177+ lfs : true
178+ fetch-depth : 2
179+
180+ - name : Ensures git ownership check does not lead to compile error
181+ run : git config --global --add safe.directory "$GITHUB_WORKSPACE"
182+
183+ - name : Create nixbuild users/group
184+ run : |
185+ addgroup nixbld
186+ adduser -D nixbld-1
187+ adduser -D nixbld-2
188+ adduser -D nixbld-3
189+ sed 's/nixbld:x:\([[:digit:]]*\):$/nixbld:x:\1:nixbld-1,nixbld-2,nixbld-3/' /etc/group > group-changed
190+ mv group-changed /etc/group
191+
192+ - uses : cachix/install-nix-action@v25
193+ with :
194+ nix_path : nixpkgs=channel:nixos-25.05
195+ extra_nix_config : " build-users-group = nixbld"
196+
197+ # Restore caches populated by the build job.
198+ - uses : actions/cache@v5
199+ name : Cache cabal store
200+ with :
201+ path : ${{ steps.setup-haskell.outputs.cabal-store || '~/.local/state/cabal' }}
202+ key : ${{ runner.os }}-${{ env.GHC_VERSION }}-cabal-cache-${{ hashFiles('spectrometer.cabal', 'cabal.project.ci.linux', 'cabal.project.common') }}
203+ restore-keys : |
204+ ${{ runner.os }}-${{ env.GHC_VERSION }}-cabal-cache-
205+
206+ - uses : actions/cache@v5
207+ name : Cache dist-newstyle
208+ with :
209+ path : ${{ github.workspace }}/dist-newstyle
210+ key : ${{ runner.os }}-${{ env.GHC_VERSION }}-dist-newstyle-${{ needs.build.outputs.latest-tag }}-${{ hashFiles('spectrometer.cabal', 'cabal.project.ci.linux', 'cabal.project.common') }}
211+ restore-keys : |
212+ ${{ runner.os }}-${{ env.GHC_VERSION }}-dist-newstyle-${{ needs.build.outputs.latest-tag }}-
213+ ${{ runner.os }}-${{ env.GHC_VERSION }}-dist-newstyle-
214+
215+ # extra-source-files (vendor-bins/*, target/release/*) must exist on
216+ # disk or cabal recompiles EmbeddedBinary.hs (fails under -Werror).
217+ - uses : actions/download-artifact@v4
218+ with :
219+ name : vendor-bins
220+ path : vendor-bins/
221+
222+ - uses : actions/download-artifact@v4
223+ with :
224+ name : rust-release-bins
225+ path : target/release/
226+
227+ - name : Run integration tests (${{ matrix.group }})
228+ run : |
229+ cabal update
230+ MATCH_ARGS=""
231+ for pattern in ${{ matrix.matches }}; do
232+ MATCH_ARGS="$MATCH_ARGS --test-option=--match --test-option=$pattern"
233+ done
234+ cabal test --project-file=cabal.project.ci.linux \
235+ --test-show-details=direct \
236+ --test-option=--times \
237+ $MATCH_ARGS \
238+ integration-tests \
239+ --test-options="+RTS -N -RTS"
0 commit comments