3 # We use bash as default even in windows
4 # to try keep the workflow as uniform as possible
9 # See: https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#concurrency.
11 group: ${{ github.ref }}-${{ github.workflow }}
12 cancel-in-progress: true
24 # We choose a stable ghc version across all os's
25 # which will be used to do the next release
26 GHC_FOR_RELEASE: '9.2.3'
27 # Ideally we should use the version about to be released for hackage tests and benchmarks
28 GHC_FOR_SOLVER_BENCHMARKS: '9.2.3'
29 GHC_FOR_COMPLETE_HACKAGE_TESTS: '9.2.3'
30 COMMON_FLAGS: '-j 2 -v'
34 name: Validate ${{ matrix.os }} ghc-${{ matrix.ghc }}
35 runs-on: ${{ matrix.os }}
37 GHC_FOR_RELEASE: ${{ format('["{0}"]', env.GHC_FOR_RELEASE) }}
40 os: ["ubuntu-20.04", "macos-latest", "windows-latest"]
41 ghc: ["9.4.2", "9.2.3", "9.0.2", "8.10.7", "8.8.4", "8.6.5", "8.4.4"]
43 # corrupts GHA cache or the fabric of reality itself, see https://github.com/haskell/cabal/issues/8356
44 - os: "windows-latest"
46 # lot of segfaults caused by ghc bugs
47 - os: "windows-latest"
49 # it also throws segfaults randomly
50 - os: "windows-latest"
52 # it often randomly does "C:\Users\RUNNER~1\AppData\Local\Temp\ghcFEDE.c: DeleteFile "\\\\?\\C:\\Users\\RUNNER~1\\AppData\\Local\\Temp\\ghcFEDE.c": permission denied (Access is denied.)"
53 - os: "windows-latest"
58 - uses: actions/checkout@v3
60 # See the following link for a breakdown of the following step
61 # https://github.com/haskell/actions/issues/7#issuecomment-745697160
63 # See https://github.com/haskell/cabal/pull/8739 for why Windows is excluded
64 - if: ${{ runner.os != 'Windows' }}
65 uses: actions/cache@v3
67 # validate.sh uses a special build dir
69 ${{ steps.setup-haskell.outputs.cabal-store }}
71 key: ${{ runner.os }}-${{ matrix.ghc }}-20220419-${{ github.sha }}
72 restore-keys: ${{ runner.os }}-${{ matrix.ghc }}-20220419-
74 # See https://github.com/haskell/cabal/pull/8739
75 - name: Sudo chmod to permit ghcup to update its cache
77 if [[ "${{ runner.os }}" == "Linux" ]]; then
78 sudo ls -lah /usr/local/.ghcup/cache
79 sudo mkdir -p /usr/local/.ghcup/cache
80 sudo ls -lah /usr/local/.ghcup/cache
81 sudo chown -R $USER /usr/local/.ghcup
82 sudo chmod -R 777 /usr/local/.ghcup
84 - uses: haskell/actions/setup@v2
87 ghc-version: ${{ matrix.ghc }}
88 cabal-version: '3.10.1.0'
90 - name: Work around git problem https://bugs.launchpad.net/ubuntu/+source/git/+bug/1993586 (cabal PR #8546)
92 git config --global protocol.file.allow always
94 # The '+exe' constraint below is important, otherwise cabal-install
95 # might decide to build the library but not the executable which is
97 - name: Install cabal-plan
100 cabal install cabal-plan --allow-newer="base" --constraint='cabal-plan +exe'
101 echo "$HOME/.cabal/bin:$HOME/.local/bin" >> $GITHUB_PATH
103 # The tool is not essential to the rest of the test suite. If
104 # hackage-repo-tool is not present, any test that requires it will
106 # We want to keep this in the loop but we don't want to fail if
107 # hackage-repo-tool breaks or fails to support a newer GHC version.
108 - name: Install hackage-repo-tool
109 continue-on-error: true
112 cabal install hackage-repo-tool
114 # Needed by cabal-testsuite/PackageTests/Configure/setup.test.hs
115 - name: Install Autotools
116 if: runner.os == 'macOS'
118 brew install automake
120 - name: Set validate inputs
122 FLAGS="${{ env.COMMON_FLAGS }}"
123 if [[ "${{ matrix.cli }}" == "false" ]]; then
124 FLAGS="$FLAGS --lib-only"
126 if [[ ${{ matrix.ghc }} == ${{ env.GHC_FOR_SOLVER_BENCHMARKS }} ]]; then
127 FLAGS="$FLAGS --solver-benchmarks"
129 if [[ ${{ matrix.ghc }} == ${{ env.GHC_FOR_COMPLETE_HACKAGE_TESTS }} ]]; then
130 FLAGS="$FLAGS --complete-hackage-tests"
132 echo "FLAGS=$FLAGS" >> $GITHUB_ENV
134 - name: Allow newer dependencies when built with latest GHC
135 if: ${{ matrix.ghc }} == '9.6.1'
137 echo "allow-newer: rere:base, rere:transformers" >> cabal.project.validate
139 - name: Validate print-config
140 run: sh validate.sh $FLAGS -s print-config
142 - name: Validate print-tool-versions
143 run: sh validate.sh $FLAGS -s print-tool-versions
145 - name: Validate build
146 run: sh validate.sh $FLAGS -s build
148 - name: Tar cabal head executable
149 if: matrix.cli != 'false' && matrix.ghc == env.GHC_FOR_RELEASE
151 CABAL_EXEC=$(cabal-plan list-bin --builddir=dist-newstyle-validate-ghc-${{ matrix.ghc }} cabal-install:exe:cabal)
152 # We have to tar the executable to preserve executable permissions
153 # see https://github.com/actions/upload-artifact/issues/38
154 if [[ ${{ runner.os }} == 'Windows' ]]; then
155 # `cabal-plan` gives us a windows path but tar needs the posix one
156 CABAL_EXEC=$(cygpath $CABAL_EXEC)
158 if [[ "${{ runner.os }}" == "macOS" ]]; then
159 # Workaround to avoid bsdtar corrupts the executable
160 # so executing it after untar throws `cannot execute binary file`
161 # see https://github.com/actions/virtual-environments/issues/2619#issuecomment-788397841
164 tar -cvf cabal-head.tar -C $(dirname "$CABAL_EXEC") $(basename "$CABAL_EXEC")
165 echo "CABAL_EXEC_TAR=cabal-head.tar" >> $GITHUB_ENV
167 # We upload the cabal executable built with the ghc used in the release for:
168 # - Reuse it in the dogfooding job (although we could use the cached build dir)
169 # - Make it available in the workflow to make easier testing it locally
170 - name: Upload cabal-install executable to workflow artifacts
171 if: matrix.cli != 'false' && matrix.ghc == env.GHC_FOR_RELEASE
172 uses: actions/upload-artifact@v3
174 name: cabal-${{ runner.os }}-${{ matrix.ghc }}
175 path: ${{ env.CABAL_EXEC_TAR }}
177 - name: Validate lib-tests
179 # `rawSystemStdInOut reports text decoding errors`
180 # test does not find ghc without the full path in windows
181 GHCPATH: ${{ steps.setup-haskell.outputs.ghc-exe }}
182 run: sh validate.sh $FLAGS -s lib-tests
184 - name: Validate lib-suite
185 # Have to disable *-suite validation:
186 # - the Windows@9.6.1 problem is tracked at https://github.com/haskell/cabal/issues/8858
187 # - but curently can't run it with GHC 9.6, tracking: https://github.com/haskell/cabal/issues/8883
188 if: (runner.os != 'Windows') || (matrix.ghc != '9.6.1')
189 run: sh validate.sh $FLAGS -s lib-suite
191 - name: Validate cli-tests
192 if: matrix.cli != 'false'
193 run: sh validate.sh $FLAGS -s cli-tests
195 - name: Validate cli-suite
196 # Have to disable *-suite validation, see above the comment for lib-suite
197 if: ((runner.os != 'Windows') || (matrix.ghc != '9.6.1')) && (matrix.cli != 'false')
198 run: sh validate.sh $FLAGS -s cli-suite
200 # The job below is a copy-paste of validate with the necessary tweaks
201 # to make all work with an upcoming GHC. Those tweaks include:
202 # - ghcup needs the prerelease channel activated
203 # - allow-newer for base libraries and Cabal* libraries
204 # - (sometimes) disabling some parts on Windows because it's hard to figure
207 # TODO: reenable when the next GHC prerelease appears
210 name: Validate ${{ matrix.os }} ghc-prerelease
211 runs-on: ${{ matrix.os }}
213 GHC_FOR_RELEASE: ${{ format('["{0}"]', env.GHC_FOR_RELEASE) }}
216 os: ["ubuntu-20.04", "macos-latest", "windows-latest"]
220 - uses: actions/checkout@v3
222 # See the following link for a breakdown of the following step
223 # https://github.com/haskell/actions/issues/7#issuecomment-745697160
225 # See https://github.com/haskell/cabal/pull/8739 for why Windows is excluded
226 - if: ${{ runner.os != 'Windows' }}
227 uses: actions/cache@v3
229 # validate.sh uses a special build dir
231 ${{ steps.setup-haskell.outputs.cabal-store }}
233 key: ${{ runner.os }}-${{ matrix.ghc }}-20220419-${{ github.sha }}
234 restore-keys: ${{ runner.os }}-${{ matrix.ghc }}-20220419-
236 # See https://github.com/haskell/cabal/pull/8739
237 - name: Sudo chmod to permit ghcup to update its cache
239 if [[ "${{ runner.os }}" == "Linux" ]]; then
240 sudo ls -lah /usr/local/.ghcup/cache
241 sudo mkdir -p /usr/local/.ghcup/cache
242 sudo ls -lah /usr/local/.ghcup/cache
243 sudo chown -R $USER /usr/local/.ghcup
244 sudo chmod -R 777 /usr/local/.ghcup
250 ghcup config set cache true
251 ghcup config add-release-channel https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-prereleases-0.0.7.yaml
252 ghcup install ghc --set 9.6.0.20230210
253 ghcup install cabal --set latest
257 - name: Work around git problem https://bugs.launchpad.net/ubuntu/+source/git/+bug/1993586 (cabal PR #8546)
259 git config --global protocol.file.allow always
261 # The '+exe' constraint below is important, otherwise cabal-install
262 # might decide to build the library but not the executable which is
264 - name: Install cabal-plan
267 cabal install cabal-plan --allow-newer="base" --constraint='cabal-plan +exe'
268 echo "$HOME/.cabal/bin:$HOME/.local/bin" >> $GITHUB_PATH
270 # The tool is not essential to the rest of the test suite. If
271 # hackage-repo-tool is not present, any test that requires it will
273 # We want to keep this in the loop but we don't want to fail if
274 # hackage-repo-tool breaks or fails to support a newer GHC version.
275 - name: Install hackage-repo-tool
276 continue-on-error: true
279 cabal install hackage-repo-tool
281 # Needed by cabal-testsuite/PackageTests/Configure/setup.test.hs
282 - name: Install Autotools
283 if: runner.os == 'macOS'
285 brew install automake
287 - name: Allow newer boot libraries
289 echo "allow-newer: base, template-haskell, ghc-prim, Cabal-syntax, Cabal-described, Cabal, cabal-install-solver, cabal-install" >> cabal.project.validate
291 - name: Set validate inputs
293 FLAGS="${{ env.COMMON_FLAGS }}"
294 if [[ "${{ matrix.cli }}" == "false" ]]; then
295 FLAGS="$FLAGS --lib-only"
297 echo "FLAGS=$FLAGS" >> $GITHUB_ENV
299 - name: Validate print-config
300 run: sh validate.sh $FLAGS -s print-config
302 - name: Validate print-tool-versions
303 run: sh validate.sh $FLAGS -s print-tool-versions
305 - name: Validate build
306 run: sh validate.sh $FLAGS -s build
308 - name: Validate lib-tests
310 # `rawSystemStdInOut reports text decoding errors`
311 # test does not find ghc without the full path in windows
312 GHCPATH: ${{ steps.setup-haskell.outputs.ghc-exe }}
313 run: sh validate.sh $FLAGS -s lib-tests
315 - name: Validate lib-suite
316 # see https://github.com/haskell/cabal/pull/8754#issuecomment-1435025848
317 # for discussion about the trouble on Windows
318 if: ${{ runner.os != 'Windows' }}
319 run: sh validate.sh $FLAGS -s lib-suite
321 - name: Validate cli-tests
322 if: matrix.cli != 'false'
323 run: sh validate.sh $FLAGS -s cli-tests
325 - name: Validate cli-suite
326 # see https://github.com/haskell/cabal/pull/8754#issuecomment-1435025848
327 # for discussion about the trouble on Windows
328 if: ( runner.os != 'Windows' ) && ( matrix.cli != 'false' )
329 run: sh validate.sh $FLAGS -s cli-suite
332 name: Validate old ghcs ${{ matrix.extra-ghc }}
333 runs-on: ubuntu-20.04
335 # This job needs an older ubuntu (16.04) cause
336 # the required old ghcs using the `-dyn` flavour
337 # are not installable from ppa/hvr in newer ones
338 # see https://github.com/haskell/cabal/issues/8011
340 image: phadej/ghc:8.8.4-xenial
344 # Newer ghc versions than 8.8.4 have to be installed with ghcup cause
345 # they are not available in ppa/hvr. The ghcup installation
346 # needs `sudo` which is not available in the xenial container
348 extra-ghc: ["7.10.3", "7.8.4", "7.6.3", "7.4.2", "7.2.2", "7.0.4"]
352 # We can't use actions/checkout with the xenial docker container
353 # cause it does not work with the git version included in it, see:
354 # https://github.com/actions/checkout/issues/170
355 # https://github.com/actions/checkout/issues/295
356 # - uses: actions/checkout@v3
359 echo $GITHUB_REF $GITHUB_SHA
360 git clone --depth 1 https://github.com/$GITHUB_REPOSITORY.git .
361 git fetch origin $GITHUB_SHA:temporary-ci-branch
362 git checkout $GITHUB_SHA || (git fetch && git checkout $GITHUB_SHA)
364 # As we are reusing the cached build dir from the previous step
365 # the generated artifacts are available here,
366 # including the cabal executable and the test suite
367 - uses: actions/cache@v3
370 ${{ steps.setup-haskell.outputs.cabal-store }}
372 key: ${{ runner.os }}-${{ matrix.ghc }}-20220419-${{ github.sha }}
373 restore-keys: ${{ runner.os }}-${{ matrix.ghc }}-20220419-
375 - name: Install extra compiler
378 apt-get install -y ghc-${{ matrix.extra-ghc }}-dyn
380 - uses: haskell/actions/setup@v2
383 ghc-version: ${{ matrix.ghc }}
384 cabal-version: latest # latest is mandatory for cabal-testsuite, see https://github.com/haskell/cabal/issues/8133
386 - name: Install cabal-plan
389 cabal install cabal-plan --allow-newer="base" --constraint='cabal-plan +exe'
390 echo "$HOME/.cabal/bin:$HOME/.local/bin" >> $GITHUB_PATH
392 - name: Validate build
393 run: sh validate.sh ${{ env.COMMON_FLAGS }} -s build
395 - name: "Validate lib-suite-extras --extra-hc ghc-${{ matrix.extra-ghc }}"
397 EXTRA_GHC: "/opt/ghc/${{ matrix.extra-ghc }}/bin/ghc-${{ matrix.extra-ghc }}"
398 run: sh validate.sh ${{ env.COMMON_FLAGS }} --lib-only -s lib-suite-extras --extra-hc ${{ env.EXTRA_GHC }}
400 # The previous jobs use a released version of cabal to build cabal HEAD itself
401 # This one uses the cabal HEAD generated executable in the previous step
402 # to build itself again, as sanity check
404 name: Dogfooding ${{ matrix.os }} ghc-${{ matrix.ghc }}
405 runs-on: ${{ matrix.os }}
409 os: ["ubuntu-20.04", "macos-latest", "windows-latest"]
410 # We only use one ghc version the used one for the next release (defined at top of the workflow)
411 # We need to build an array dynamically to inject the appropiate env var in a previous job,
412 # see https://docs.github.com/en/actions/learn-github-actions/expressions#fromjson
413 ghc: ${{ fromJSON (needs.validate.outputs.GHC_FOR_RELEASE) }}
416 - uses: actions/checkout@v3
418 # See https://github.com/haskell/cabal/pull/8739
419 - name: Sudo chmod to permit ghcup to update its cache
421 if [[ "${{ runner.os }}" == "Linux" ]]; then
422 sudo ls -lah /usr/local/.ghcup/cache
423 sudo mkdir -p /usr/local/.ghcup/cache
424 sudo ls -lah /usr/local/.ghcup/cache
425 sudo chown -R $USER /usr/local/.ghcup
426 sudo chmod -R 777 /usr/local/.ghcup
428 - uses: haskell/actions/setup@v2
431 ghc-version: ${{ matrix.ghc }}
432 cabal-version: latest # default, we are not using it in this job
434 - name: Install cabal-plan
437 cabal install cabal-plan --allow-newer="base" --constraint='cabal-plan +exe'
438 echo "$HOME/.cabal/bin:$HOME/.local/bin" >> $GITHUB_PATH
440 - name: Download cabal executable from workflow artifacts
441 uses: actions/download-artifact@v3
443 name: cabal-${{ runner.os }}-${{ matrix.ghc }}
446 - name: Untar the cabal executable
447 run: tar -xf ./cabal-head/cabal-head.tar -C ./cabal-head
449 - name: print-config using cabal HEAD
450 run: sh validate.sh ${{ env.COMMON_FLAGS }} --with-cabal ./cabal-head/cabal -s print-config
452 # We dont use cache to force a build with a fresh store dir and build dir
453 # This way we check cabal can build all its dependencies
454 - name: Build using cabal HEAD
455 run: sh validate.sh ${{ env.COMMON_FLAGS }} --with-cabal ./cabal-head/cabal -s build
457 # We use this job as a summary of the workflow
458 # It will fail if any of the previous jobs does it
459 # This way we can use it exclusively in branch protection rules
460 # and abstract away the concrete jobs of the workflow, including their names
463 name: Validate post job
464 runs-on: ubuntu-20.04
465 # IMPORTANT! Any job added to the workflow should be added here too
466 needs: [validate, validate-old-ghcs, dogfooding]
470 echo "jobs info: ${{ toJSON(needs) }}"
471 - if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')