ci: Drop validate 8.4.4 job.
[cabal.git] / .github / workflows / validate.yml
blobd1f6bb54fd4cefcab1c421953b176b9bd13ecd65
1 name: Validate
3 # We use bash as default even in windows
4 # to try keep the workflow as uniform as possible
5 defaults:
6   run:
7     shell: bash
9 # See: https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#concurrency.
10 concurrency:
11   group: ${{ github.ref }}-${{ github.workflow }}
12   cancel-in-progress: true
14 # Note: This workflow file contains the required job "Validate post job". We are using path filtering
15 # here to ignore PRs which only change documentation. This can cause a problem, see the workflow file
16 # "validate.skip.yml" for a description of the problem and the solution provided in that file.
17 on:
18   push:
19     paths-ignore:
20       - 'doc/**'
21       - '**/README.md'
22       - 'CONTRIBUTING.md'
23     branches:
24       - master
25   pull_request:
26     paths-ignore:
27       - 'doc/**'
28       - '**/README.md'
29       - 'CONTRIBUTING.md'
30   release:
31     types:
32       - created
33   workflow_call:
35   # See https://github.com/haskell/cabal/blob/master/CONTRIBUTING.md#hackage-revisions
36   workflow_dispatch:
37     inputs:
38       allow-newer:
39         description: allow-newer line
40         required: true
41         type: string
42       constraints:
43         description: constraints line
44         required: true
45         type: string
47 env:
48   # We choose a stable ghc version across all os's
49   # which will be used to do the next release
50   GHC_FOR_RELEASE: '9.2.8'
51   # Ideally we should use the version about to be released for hackage tests and benchmarks
52   GHC_FOR_SOLVER_BENCHMARKS: '9.2.8'
53   GHC_FOR_COMPLETE_HACKAGE_TESTS: '9.2.8'
54   COMMON_FLAGS: '-j 2 -v'
56   # See https://github.com/haskell/cabal/blob/master/CONTRIBUTING.md#hackage-revisions
57   ALLOWNEWER: ${{ github.event.inputs.allow-newer }}
58   CONSTRAINTS: ${{ github.event.inputs.constraints }}
61 jobs:
62   validate:
63     name: Validate ${{ matrix.os }} ghc-${{ matrix.ghc }}
64     runs-on: ${{ matrix.os }}
65     outputs:
66       GHC_FOR_RELEASE: ${{ format('["{0}"]', env.GHC_FOR_RELEASE) }}
67     strategy:
68       matrix:
69         os: ["ubuntu-latest", "macos-latest", "windows-latest"]
70         ghc: ["9.8.1", "9.6.3", "9.4.8", "9.2.8", "9.0.2", "8.10.7", "8.8.4", "8.6.5"]
71         exclude:
72           # corrupts GHA cache or the fabric of reality itself, see https://github.com/haskell/cabal/issues/8356
73           - os: "windows-latest"
74             ghc: "8.10.7"
75           # lot of segfaults caused by ghc bugs
76           - os: "windows-latest"
77             ghc: "8.8.4"
78           # it also throws segfaults randomly
79           - os: "windows-latest"
80             ghc: "8.4.4"
81           # 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.)"
82           - os: "windows-latest"
83             ghc: "8.6.5"
85     steps:
87       - name: Work around XDG directories existence (haskell-actions/setup#62)
88         if: ${{ runner.os == 'macOS' }}
89         run: |
90           rm -rf ~/.config/cabal
91           rm -rf ~/.cache/cabal
93       - uses: actions/checkout@v4
95       # See https://github.com/haskell/cabal/blob/master/CONTRIBUTING.md#hackage-revisions
96       - name: Manually supplied constraints/allow-newer
97         if: ${{ github.event_name == 'workflow_dispatch' }}
98         run: |
99           echo 'allow-newer:' ${ALLOWNEWER}  >> cabal.project.validate
100           echo 'constraints:' ${CONSTRAINTS} >> cabal.project.validate
102       #  See the following link for a breakdown of the following step
103       #  https://github.com/haskell/actions/issues/7#issuecomment-745697160
104       - uses: actions/cache@v3
105         with:
106           # validate.sh uses a special build dir
107           path: |
108             ${{ steps.setup-haskell.outputs.cabal-store }}
109             dist-*
110           key: ${{ runner.os }}-${{ matrix.ghc }}-${{ github.sha }}
111           restore-keys: ${{ runner.os }}-${{ matrix.ghc }}-
113       - uses: haskell-actions/setup@v2
114         id: setup-haskell
115         with:
116           ghc-version: ${{ matrix.ghc }}
117           cabal-version: latest # latest is mandatory for cabal-testsuite, see https://github.com/haskell/cabal/issues/8133
119       - name: Work around git problem https://bugs.launchpad.net/ubuntu/+source/git/+bug/1993586 (cabal PR #8546)
120         run: |
121           git config --global protocol.file.allow always
123       # The tool is not essential to the rest of the test suite. If
124       # hackage-repo-tool is not present, any test that requires it will
125       # be skipped.
126       # We want to keep this in the loop but we don't want to fail if
127       # hackage-repo-tool breaks or fails to support a newer GHC version.
128       - name: Install hackage-repo-tool
129         continue-on-error: true
130         run: |
131           cd $(mktemp -d)
132           cabal install hackage-repo-tool
134       # Needed by cabal-testsuite/PackageTests/Configure/setup.test.hs
135       - name: Install Autotools
136         if: runner.os == 'macOS'
137         run: |
138           brew install automake
140       - name: Set validate inputs
141         run: |
142           FLAGS="${{ env.COMMON_FLAGS }}"
143           if [[ ${{ matrix.ghc }} == ${{ env.GHC_FOR_SOLVER_BENCHMARKS }} ]]; then
144             FLAGS="$FLAGS --solver-benchmarks"
145           fi
146           if [[ ${{ matrix.ghc }} == ${{ env.GHC_FOR_COMPLETE_HACKAGE_TESTS }} ]]; then
147             FLAGS="$FLAGS --complete-hackage-tests"
148           fi
149           echo "FLAGS=$FLAGS" >> $GITHUB_ENV
151       - name: Validate print-config
152         run: sh validate.sh $FLAGS -s print-config
154       - name: Validate print-tool-versions
155         run: sh validate.sh $FLAGS -s print-tool-versions
157       - name: Validate build
158         run: sh validate.sh $FLAGS -s build
160       - name: Tar cabal head executable
161         if: matrix.ghc == env.GHC_FOR_RELEASE
162         run: |
163           CABAL_EXEC=$(cabal list-bin --builddir=dist-newstyle-validate-ghc-${{ matrix.ghc }} --project-file=cabal.project.validate cabal-install:exe:cabal)
164           # We have to tar the executable to preserve executable permissions
165           # see https://github.com/actions/upload-artifact/issues/38
166           if [[ ${{ runner.os }} == 'Windows' ]]; then
167             # `cabal list-bin` gives us a windows path but tar needs the posix one
168             CABAL_EXEC=$(cygpath $CABAL_EXEC)
169           fi
170           if [[ "${{ runner.os }}" == "macOS" ]]; then
171              # Workaround to avoid bsdtar corrupts the executable
172              # so executing it after untar throws `cannot execute binary file`
173              # see https://github.com/actions/virtual-environments/issues/2619#issuecomment-788397841
174              sudo /usr/sbin/purge
175           fi
176           export CABAL_EXEC_TAR="cabal-head-${{ runner.os }}-x86_64.tar.gz"
177           tar -czvf $CABAL_EXEC_TAR -C $(dirname "$CABAL_EXEC") $(basename "$CABAL_EXEC")
178           echo "CABAL_EXEC_TAR=$CABAL_EXEC_TAR" >> $GITHUB_ENV
180       # We upload the cabal executable built with the ghc used in the release for:
181       # - Reuse it in the dogfooding job (although we could use the cached build dir)
182       # - Make it available in the workflow to make easier testing it locally
183       - name: Upload cabal-install executable to workflow artifacts
184         if: matrix.ghc == env.GHC_FOR_RELEASE
185         uses: actions/upload-artifact@v3
186         with:
187           name: cabal-${{ runner.os }}-x86_64
188           path: ${{ env.CABAL_EXEC_TAR }}
190       - name: Validate lib-tests
191         env:
192           # `rawSystemStdInOut reports text decoding errors`
193           # test does not find ghc without the full path in windows
194           GHCPATH: ${{ steps.setup-haskell.outputs.ghc-exe }}
195         run: sh validate.sh $FLAGS -s lib-tests
197       - name: Validate lib-suite
198         # Have to disable *-suite validation:
199         # - the Windows@9.6.1 problem is tracked at https://github.com/haskell/cabal/issues/8858
200         # - but curently can't run it with GHC 9.6, tracking: https://github.com/haskell/cabal/issues/8883
201         run: sh validate.sh $FLAGS -s lib-suite
203       - name: Validate cli-tests
204         run: sh validate.sh $FLAGS -s cli-tests
206       - name: Validate cli-suite
207         # Have to disable *-suite validation, see above the comment for lib-suite
208         run: sh validate.sh $FLAGS -s cli-suite
210       - name: Validate solver-benchmarks-tests
211         run: |
212           if [[ ${{ matrix.ghc }} == ${{ env.GHC_FOR_SOLVER_BENCHMARKS }} ]]; then
213             sh validate.sh $FLAGS -s solver-benchmarks-tests
214           fi
216       - name: Validate solver-benchmarks-run
217         run: |
218           if [[ ${{ matrix.ghc }} == ${{ env.GHC_FOR_SOLVER_BENCHMARKS }} ]]; then
219             sh validate.sh $FLAGS -s solver-benchmarks-run
220           fi
222   validate-old-ghcs:
223     name: Validate old ghcs ${{ matrix.extra-ghc }}
224     runs-on: ubuntu-latest
225     needs: validate
226     # This job needs an older ubuntu (16.04) cause
227     # the required old ghcs using the `-dyn` flavour
228     # are not installable from ppa/hvr in newer ones
229     # see https://github.com/haskell/cabal/issues/8011
230     container:
231       image: phadej/ghc:8.8.4-xenial
233     strategy:
234       matrix:
235         # Newer ghc versions than 8.8.4 have to be installed with ghcup cause
236         # they are not available in ppa/hvr. The ghcup installation
237         # needs `sudo` which is not available in the xenial container
238         ghc: ["8.8.4"]
239         extra-ghc: ["7.10.3", "7.8.4", "7.6.3", "7.4.2", "7.2.2", "7.0.4"]
241     steps:
243       # We can't use actions/checkout with the xenial docker container
244       # cause it does not work with the git version included in it, see:
245       # https://github.com/actions/checkout/issues/170
246       # https://github.com/actions/checkout/issues/295
247       # - uses: actions/checkout@v4
248       - name: Checkout
249         run: |
250           echo $GITHUB_REF $GITHUB_SHA
251           git clone --depth 1 https://github.com/$GITHUB_REPOSITORY.git .
252           git fetch origin $GITHUB_SHA:temporary-ci-branch
253           git checkout $GITHUB_SHA || (git fetch && git checkout $GITHUB_SHA)
255       - name: Install extra compiler
256         run: |
257           apt-get update
258           apt-get install -y ghc-${{ matrix.extra-ghc }}-dyn
260       - uses: haskell-actions/setup@v2
261         id: setup-haskell
262         with:
263           ghc-version: ${{ matrix.ghc }}
264           # Make sure this bindist works in this old environment
265           cabal-version: 3.10.1.0
267       # As we are reusing the cached build dir from the previous step
268       # the generated artifacts are available here,
269       # including the cabal executable and the test suite
270       - uses: actions/cache@v3
271         with:
272           path: |
273             ${{ steps.setup-haskell.outputs.cabal-store }}
274             dist-*
275           key: ${{ runner.os }}-${{ matrix.ghc }}-${{ github.sha }}
276           restore-keys: ${{ runner.os }}-${{ matrix.ghc }}-
278       - name: Validate build
279         run: sh validate.sh ${{ env.COMMON_FLAGS }} -s build
281       - name: "Validate lib-suite-extras --extra-hc ghc-${{ matrix.extra-ghc }}"
282         env:
283           EXTRA_GHC: "/opt/ghc/${{ matrix.extra-ghc }}/bin/ghc-${{ matrix.extra-ghc }}"
284         run: sh validate.sh ${{ env.COMMON_FLAGS }} --lib-only -s lib-suite-extras --extra-hc ${{ env.EXTRA_GHC }}
286   build-alpine:
287     name: Build statically linked using alpine 
288     runs-on: "ubuntu-latest"
289     container: "alpine:3.19"
290     steps:
291       - name: Install extra dependencies
292         shell: sh
293         run: |
294           apk add bash curl sudo jq pkgconfig \
295           zlib-dev zlib-static binutils-gold curl \
296           gcc g++ gmp-dev libc-dev libffi-dev make \
297           musl-dev ncurses-dev perl tar xz
299       - uses: actions/checkout@v4
301       # See https://github.com/haskell/cabal/blob/master/CONTRIBUTING.md#hackage-revisions
302       - name: Manually supplied constraints/allow-newer
303         if: ${{ github.event_name == 'workflow_dispatch' }}
304         run: |
305           echo 'allow-newer:' ${ALLOWNEWER}  >> cabal.project.validate
306           echo 'constraints:' ${CONSTRAINTS} >> cabal.project.validate
308       #  See the following link for a breakdown of the following step
309       #  https://github.com/haskell/actions/issues/7#issuecomment-745697160
310       - uses: actions/cache@v3
311         with:
312           # validate.sh uses a special build dir
313           path: |
314             ${{ steps.setup-haskell.outputs.cabal-store }}
315             dist-*
316           key: ${{ runner.os }}-${{ env.GHC_FOR_RELEASE }}-${{ github.sha }}
317           restore-keys: ${{ runner.os }}-${{ env.GHC_FOR_RELEASE }}-
319       - uses: haskell-actions/setup@v2
320         id: setup-haskell
321         with:
322           ghc-version: ${{ env.GHC_FOR_RELEASE }}
323           cabal-version: latest # latest is mandatory for cabal-testsuite, see https://github.com/haskell/cabal/issues/8133
325       - name: Enable statically linked executables
326         run: |
327           echo 'executable-static: true' >> cabal.project.validate
329       - name: Build
330         run: sh validate.sh $FLAGS -s build
332       - name: Tar cabal head executable
333         run: |
334           CABAL_EXEC=$(cabal list-bin --builddir=dist-newstyle-validate-ghc-${{ env.GHC_FOR_RELEASE }} --project-file=cabal.project.validate cabal-install:exe:cabal)
335           # We have to tar the executable to preserve executable permissions
336           # see https://github.com/actions/upload-artifact/issues/38
337           export CABAL_EXEC_TAR="cabal-head-${{ runner.os }}-static-x86_64.tar.gz"
338           tar -czvf $CABAL_EXEC_TAR -C $(dirname "$CABAL_EXEC") $(basename "$CABAL_EXEC")
339           echo "CABAL_EXEC_TAR=$CABAL_EXEC_TAR" >> $GITHUB_ENV
341       - name: Upload cabal-install executable to workflow artifacts
342         uses: actions/upload-artifact@v3
343         with:
344           name: cabal-${{ runner.os }}-static-x86_64
345           path: ${{ env.CABAL_EXEC_TAR }}
348   # The previous jobs use a released version of cabal to build cabal HEAD itself
349   # This one uses the cabal HEAD generated executable in the previous step
350   # to build itself again, as sanity check
351   dogfooding:
352     name: Dogfooding ${{ matrix.os }} ghc-${{ matrix.ghc }}
353     runs-on: ${{ matrix.os }}
354     needs: validate
355     strategy:
356       matrix:
357         os: ["ubuntu-latest", "macos-latest", "windows-latest"]
358         # We only use one ghc version the used one for the next release (defined at top of the workflow)
359         # We need to build an array dynamically to inject the appropiate env var in a previous job,
360         # see https://docs.github.com/en/actions/learn-github-actions/expressions#fromjson
361         ghc: ${{ fromJSON (needs.validate.outputs.GHC_FOR_RELEASE) }}
363     steps:
364       - name: Work around XDG directories existence (haskell-actions/setup#62)
365         if: ${{ runner.os == 'macOS' }}
366         run: |
367           rm -rf ~/.config/cabal
368           rm -rf ~/.cache/cabal
370       - uses: actions/checkout@v4
372       # See https://github.com/haskell/cabal/pull/8739
373       - name: Sudo chmod to permit ghcup to update its cache
374         run: |
375           if [[ "${{ runner.os }}" == "Linux" ]]; then
376             sudo ls -lah /usr/local/.ghcup/cache
377             sudo mkdir -p /usr/local/.ghcup/cache
378             sudo ls -lah /usr/local/.ghcup/cache
379             sudo chown -R $USER /usr/local/.ghcup
380             sudo chmod -R 777 /usr/local/.ghcup
381           fi
382       - uses: haskell-actions/setup@v2
383         id: setup-haskell
384         with:
385           ghc-version: ${{ matrix.ghc }}
386           cabal-version: latest # default, we are not using it in this job
388       - name: Download cabal executable from workflow artifacts
389         uses: actions/download-artifact@v3
390         with:
391           name: cabal-${{ runner.os }}-x86_64
392           path: cabal-head
394       - name: Untar the cabal executable
395         run: tar -xzf ./cabal-head/cabal-head-${{ runner.os }}-x86_64.tar.gz -C cabal-head
397       - name: print-config using cabal HEAD
398         run: sh validate.sh ${{ env.COMMON_FLAGS }} --with-cabal ./cabal-head/cabal -s print-config
400       # We dont use cache to force a build with a fresh store dir and build dir
401       # This way we check cabal can build all its dependencies
402       - name: Build using cabal HEAD
403         run: sh validate.sh ${{ env.COMMON_FLAGS }} --with-cabal ./cabal-head/cabal -s build
405   prerelease-head:
406     name: Create a GitHub prerelease with the binary artifacts
407     runs-on: ubuntu-latest
408     if: github.ref == 'refs/heads/master'
410     # IMPORTANT! Any job added to the workflow should be added here too
411     needs: [validate, validate-old-ghcs, build-alpine, dogfooding]
413     steps:
414     - uses: actions/download-artifact@v3
415       with:
416         name: cabal-Windows-x86_64
418     - uses: actions/download-artifact@v3
419       with:
420         name: cabal-Linux-x86_64
422     - uses: actions/download-artifact@v3
423       with:
424         name: cabal-Linux-static-x86_64
426     - uses: actions/download-artifact@v3
427       with:
428         name: cabal-macOS-x86_64
430     - name: Create GitHub prerelease
431       uses: "marvinpinto/action-automatic-releases@v1.2.1"
432       with:
433         repo_token: "${{ secrets.GITHUB_TOKEN }}"
434         automatic_release_tag: "cabal-head"
435         prerelease: true
436         title: "cabal-head"
437         files: |
438           cabal-head-Windows-x86_64.tar.gz
439           cabal-head-Linux-x86_64.tar.gz
440           cabal-head-Linux-static-x86_64.tar.gz
441           cabal-head-macOS-x86_64.tar.gz
443   # We use this job as a summary of the workflow
444   # It will fail if any of the previous jobs does it
445   # This way we can use it exclusively in branch protection rules
446   # and abstract away the concrete jobs of the workflow, including their names
447   validate-post-job:
448     if: always()
449     name: Validate post job
450     runs-on: ubuntu-latest
451     # IMPORTANT! Any job added to the workflow should be added here too
452     needs: [validate, validate-old-ghcs, build-alpine, dogfooding]
454     steps:
455       - run: |
456           echo "jobs info: ${{ toJSON(needs) }}"
457       - if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')
458         run: exit 1