Fix issue/PR templates (#9117)
[cabal.git] / .github / workflows / validate.yml
blob00512be6120af894eb199bb8494a7de258905a59
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 on:
15   push:
16     branches:
17       - master
18   pull_request:
19   release:
20     types:
21       - created
23 env:
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.7'
27   # Ideally we should use the version about to be released for hackage tests and benchmarks
28   GHC_FOR_SOLVER_BENCHMARKS: '9.2.7'
29   GHC_FOR_COMPLETE_HACKAGE_TESTS: '9.2.7'
30   COMMON_FLAGS: '-j 2 -v'
32 jobs:
33   validate:
34     name: Validate ${{ matrix.os }} ghc-${{ matrix.ghc }}
35     runs-on: ${{ matrix.os }}
36     outputs:
37       GHC_FOR_RELEASE: ${{ format('["{0}"]', env.GHC_FOR_RELEASE) }}
38     strategy:
39       matrix:
40         os: ["ubuntu-latest", "macos-latest", "windows-latest"]
41         ghc: ["9.6.1", "9.4.4", "9.2.7", "9.0.2", "8.10.7", "8.8.4", "8.6.5", "8.4.4"]
42         exclude:
43           # corrupts GHA cache or the fabric of reality itself, see https://github.com/haskell/cabal/issues/8356
44           - os: "windows-latest"
45             ghc: "8.10.7"
46           # lot of segfaults caused by ghc bugs
47           - os: "windows-latest"
48             ghc: "8.8.4"
49           # it also throws segfaults randomly
50           - os: "windows-latest"
51             ghc: "8.4.4"
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"
54             ghc: "8.6.5"
56     steps:
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
62       - uses: actions/cache@v3
63         with:
64           # validate.sh uses a special build dir
65           path: |
66             ${{ steps.setup-haskell.outputs.cabal-store }}
67             dist-*
68           key: ${{ runner.os }}-${{ matrix.ghc }}-${{ github.sha }}
69           restore-keys: ${{ runner.os }}-${{ matrix.ghc }}-
71       - uses: haskell/actions/setup@v2
72         id: setup-haskell
73         with:
74           ghc-version: ${{ matrix.ghc }}
75           cabal-version: '3.10.1.0'
77       - name: Work around git problem https://bugs.launchpad.net/ubuntu/+source/git/+bug/1993586 (cabal PR #8546)
78         run: |
79           git config --global protocol.file.allow always
81       # The tool is not essential to the rest of the test suite. If
82       # hackage-repo-tool is not present, any test that requires it will
83       # be skipped.
84       # We want to keep this in the loop but we don't want to fail if
85       # hackage-repo-tool breaks or fails to support a newer GHC version.
86       - name: Install hackage-repo-tool
87         continue-on-error: true
88         run: |
89           cd $(mktemp -d)
90           cabal install hackage-repo-tool
92       # Needed by cabal-testsuite/PackageTests/Configure/setup.test.hs
93       - name: Install Autotools
94         if: runner.os == 'macOS'
95         run: |
96           brew install automake
98       - name: Set validate inputs
99         run: |
100           FLAGS="${{ env.COMMON_FLAGS }}"
101           if [[ ${{ matrix.ghc }} == ${{ env.GHC_FOR_SOLVER_BENCHMARKS }} ]]; then
102             FLAGS="$FLAGS --solver-benchmarks"
103           fi
104           if [[ ${{ matrix.ghc }} == ${{ env.GHC_FOR_COMPLETE_HACKAGE_TESTS }} ]]; then
105             FLAGS="$FLAGS --complete-hackage-tests"
106           fi
107           echo "FLAGS=$FLAGS" >> $GITHUB_ENV
109       - name: Allow newer dependencies when built with latest GHC
110         if: ${{ matrix.ghc }} == '9.6.1'
111         run: |
112           echo "allow-newer: rere:base, rere:transformers" >> cabal.project.validate
114       - name: Validate print-config
115         run: sh validate.sh $FLAGS -s print-config
117       - name: Validate print-tool-versions
118         run: sh validate.sh $FLAGS -s print-tool-versions
120       - name: Validate build
121         run: sh validate.sh $FLAGS -s build
123       - name: Tar cabal head executable
124         if: matrix.ghc == env.GHC_FOR_RELEASE
125         run: |
126           CABAL_EXEC=$(cabal list-bin --builddir=dist-newstyle-validate-ghc-${{ matrix.ghc }} --project-file=cabal.project.validate cabal-install:exe:cabal)
127           # We have to tar the executable to preserve executable permissions
128           # see https://github.com/actions/upload-artifact/issues/38
129           if [[ ${{ runner.os }} == 'Windows' ]]; then
130             # `cabal list-bin` gives us a windows path but tar needs the posix one
131             CABAL_EXEC=$(cygpath $CABAL_EXEC)
132           fi
133           if [[ "${{ runner.os }}" == "macOS" ]]; then
134              # Workaround to avoid bsdtar corrupts the executable
135              # so executing it after untar throws `cannot execute binary file`
136              # see https://github.com/actions/virtual-environments/issues/2619#issuecomment-788397841
137              sudo /usr/sbin/purge
138           fi
139           export CABAL_EXEC_TAR="cabal-head-${{ runner.os }}-x86_64.tar.gz"
140           tar -czvf $CABAL_EXEC_TAR -C $(dirname "$CABAL_EXEC") $(basename "$CABAL_EXEC")
141           echo "CABAL_EXEC_TAR=$CABAL_EXEC_TAR" >> $GITHUB_ENV
143       # We upload the cabal executable built with the ghc used in the release for:
144       # - Reuse it in the dogfooding job (although we could use the cached build dir)
145       # - Make it available in the workflow to make easier testing it locally
146       - name: Upload cabal-install executable to workflow artifacts
147         if: matrix.ghc == env.GHC_FOR_RELEASE
148         uses: actions/upload-artifact@v3
149         with:
150           name: cabal-${{ runner.os }}-x86_64
151           path: ${{ env.CABAL_EXEC_TAR }}
153       - name: Validate lib-tests
154         env:
155           # `rawSystemStdInOut reports text decoding errors`
156           # test does not find ghc without the full path in windows
157           GHCPATH: ${{ steps.setup-haskell.outputs.ghc-exe }}
158         run: sh validate.sh $FLAGS -s lib-tests
160       - name: Validate lib-suite
161         # Have to disable *-suite validation:
162         # - the Windows@9.6.1 problem is tracked at https://github.com/haskell/cabal/issues/8858
163         # - but curently can't run it with GHC 9.6, tracking: https://github.com/haskell/cabal/issues/8883
164         if: (runner.os != 'Windows')  || (matrix.ghc != '9.6.1')
165         run: sh validate.sh $FLAGS -s lib-suite
167       - name: Validate cli-tests
168         run: sh validate.sh $FLAGS -s cli-tests
170       - name: Validate cli-suite
171         # Have to disable *-suite validation, see above the comment for lib-suite
172         if: (runner.os != 'Windows')  || (matrix.ghc != '9.6.1')
173         run: sh validate.sh $FLAGS -s cli-suite
175   validate-old-ghcs:
176     name: Validate old ghcs ${{ matrix.extra-ghc }}
177     runs-on: ubuntu-latest
178     needs: validate
179     # This job needs an older ubuntu (16.04) cause
180     # the required old ghcs using the `-dyn` flavour
181     # are not installable from ppa/hvr in newer ones
182     # see https://github.com/haskell/cabal/issues/8011
183     container:
184       image: phadej/ghc:8.8.4-xenial
186     strategy:
187       matrix:
188         # Newer ghc versions than 8.8.4 have to be installed with ghcup cause
189         # they are not available in ppa/hvr. The ghcup installation
190         # needs `sudo` which is not available in the xenial container
191         ghc: ["8.8.4"]
192         extra-ghc: ["7.10.3", "7.8.4", "7.6.3", "7.4.2", "7.2.2", "7.0.4"]
194     steps:
196       # We can't use actions/checkout with the xenial docker container
197       # cause it does not work with the git version included in it, see:
198       # https://github.com/actions/checkout/issues/170
199       # https://github.com/actions/checkout/issues/295
200       # - uses: actions/checkout@v3
201       - name: Checkout
202         run: |
203           echo $GITHUB_REF $GITHUB_SHA
204           git clone --depth 1 https://github.com/$GITHUB_REPOSITORY.git .
205           git fetch origin $GITHUB_SHA:temporary-ci-branch
206           git checkout $GITHUB_SHA || (git fetch && git checkout $GITHUB_SHA)
208       - name: Install extra compiler
209         run: |
210           apt-get update
211           apt-get install -y ghc-${{ matrix.extra-ghc }}-dyn
213       - uses: haskell/actions/setup@v2
214         id: setup-haskell
215         with:
216           ghc-version: ${{ matrix.ghc }}
217           cabal-version: latest # latest is mandatory for cabal-testsuite, see https://github.com/haskell/cabal/issues/8133
219       # As we are reusing the cached build dir from the previous step
220       # the generated artifacts are available here,
221       # including the cabal executable and the test suite
222       - uses: actions/cache@v3
223         with:
224           path: |
225             ${{ steps.setup-haskell.outputs.cabal-store }}
226             dist-*
227           key: ${{ runner.os }}-${{ matrix.ghc }}-${{ github.sha }}
228           restore-keys: ${{ runner.os }}-${{ matrix.ghc }}-
230       - name: Validate build
231         run: sh validate.sh ${{ env.COMMON_FLAGS }} -s build
233       - name: "Validate lib-suite-extras --extra-hc ghc-${{ matrix.extra-ghc }}"
234         env:
235           EXTRA_GHC: "/opt/ghc/${{ matrix.extra-ghc }}/bin/ghc-${{ matrix.extra-ghc }}"
236         run: sh validate.sh ${{ env.COMMON_FLAGS }} --lib-only -s lib-suite-extras --extra-hc ${{ env.EXTRA_GHC }}
238   # The previous jobs use a released version of cabal to build cabal HEAD itself
239   # This one uses the cabal HEAD generated executable in the previous step
240   # to build itself again, as sanity check
241   dogfooding:
242     name: Dogfooding ${{ matrix.os }} ghc-${{ matrix.ghc }}
243     runs-on: ${{ matrix.os }}
244     needs: validate
245     strategy:
246       matrix:
247         os: ["ubuntu-latest", "macos-latest", "windows-latest"]
248         # We only use one ghc version the used one for the next release (defined at top of the workflow)
249         # We need to build an array dynamically to inject the appropiate env var in a previous job,
250         # see https://docs.github.com/en/actions/learn-github-actions/expressions#fromjson
251         ghc: ${{ fromJSON (needs.validate.outputs.GHC_FOR_RELEASE) }}
253     steps:
254       - uses: actions/checkout@v3
256       # See https://github.com/haskell/cabal/pull/8739
257       - name: Sudo chmod to permit ghcup to update its cache
258         run: |
259           if [[ "${{ runner.os }}" == "Linux" ]]; then
260             sudo ls -lah /usr/local/.ghcup/cache
261             sudo mkdir -p /usr/local/.ghcup/cache
262             sudo ls -lah /usr/local/.ghcup/cache
263             sudo chown -R $USER /usr/local/.ghcup
264             sudo chmod -R 777 /usr/local/.ghcup
265           fi
266       - uses: haskell/actions/setup@v2
267         id: setup-haskell
268         with:
269           ghc-version: ${{ matrix.ghc }}
270           cabal-version: latest # default, we are not using it in this job
272       - name: Download cabal executable from workflow artifacts
273         uses: actions/download-artifact@v3
274         with:
275           name: cabal-${{ runner.os }}-x86_64
276           path: cabal-head
278       - name: Untar the cabal executable
279         run: tar -xzf ./cabal-head/cabal-head-${{ runner.os }}-x86_64.tar.gz -C cabal-head
281       - name: print-config using cabal HEAD
282         run: sh validate.sh ${{ env.COMMON_FLAGS }} --with-cabal ./cabal-head/cabal -s print-config
284       # We dont use cache to force a build with a fresh store dir and build dir
285       # This way we check cabal can build all its dependencies
286       - name: Build using cabal HEAD
287         run: sh validate.sh ${{ env.COMMON_FLAGS }} --with-cabal ./cabal-head/cabal -s build
289   prerelease-head:
290     name: Create a GitHub prerelease with the binary artifacts
291     runs-on: ubuntu-latest
292     if: github.ref == 'refs/heads/master'
294     # IMPORTANT! Any job added to the workflow should be added here too
295     needs: [validate, validate-old-ghcs, dogfooding]
297     steps:
298     - uses: actions/download-artifact@v3
299       with:
300         name: cabal-Windows-x86_64
302     - uses: actions/download-artifact@v3
303       with:
304         name: cabal-Linux-x86_64
306     - uses: actions/download-artifact@v3
307       with:
308         name: cabal-macOS-x86_64
310     - name: Create GitHub prerelease
311       uses: "marvinpinto/action-automatic-releases@v1.2.1"
312       with:
313         repo_token: "${{ secrets.GITHUB_TOKEN }}"
314         automatic_release_tag: "cabal-head"
315         prerelease: true
316         title: "cabal-head"
317         files: |
318           cabal-head-Windows-x86_64.tar.gz
319           cabal-head-Linux-x86_64.tar.gz
320           cabal-head-macOS-x86_64.tar.gz
322   # We use this job as a summary of the workflow
323   # It will fail if any of the previous jobs does it
324   # This way we can use it exclusively in branch protection rules
325   # and abstract away the concrete jobs of the workflow, including their names
326   validate-post-job:
327     if: always()
328     name: Validate post job
329     runs-on: ubuntu-latest
330     # IMPORTANT! Any job added to the workflow should be added here too
331     needs: [validate, validate-old-ghcs, dogfooding]
333     steps:
334       - run: |
335           echo "jobs info: ${{ toJSON(needs) }}"
336       - if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')
337         run: exit 1