diff --git a/.github/actions/cabal-setup/action.yml b/.github/actions/cabal-setup/action.yml new file mode 100644 index 00000000000..c3fbbcb82e7 --- /dev/null +++ b/.github/actions/cabal-setup/action.yml @@ -0,0 +1,156 @@ +name: Cabal setup +description: Set up a workflow for Cabal + +inputs: + ghc: + description: ghc version to use + required: true + extra-ghc: + description: additional ghc for tests + required: false + default: '' + allow-newer: + description: allow-newer line + required: false + default: '' + constraints: + description: constraints line + required: false + default: '' + static: + description: whether to build statically + required: false + default: 'false' + shell: + description: shell to use + required: false + default: 'bash' + with_cache: + description: whether to instantiate cache + required: false + default: 'true' + +outputs: + ghc-exe: + description: Path to ghc installed by setup-haskell + value: ${{ steps.setup-haskell.outputs.ghc-exe }} + +runs: + using: composite + steps: + - name: Work around existence of XDG directories (haskell-actions/setup#62) + if: runner.os == 'macOS' + shell: ${{ inputs.shell }} + run: | + rm -rf ~/.config/cabal + rm -rf ~/.cache/cabal + + - name: "WIN: Setup TMP environment variable" + if: runner.os == 'Windows' + shell: ${{ inputs.shell }} + run: | + echo "TMP=${{ runner.temp }}" >> "$GITHUB_ENV" + + # See https://github.com/haskell/cabal/blob/master/CONTRIBUTING.md#hackage-revisions + - name: Add manually supplied allow-newer + if: inputs.allow-newer != '' + shell: ${{ inputs.shell }} + run: | + echo "allow-newer: ${{ inputs.allow-newer }}" >> cabal.validate.project + + - name: Add manually supplied constraints + if: inputs.constraints != '' + shell: ${{ inputs.shell }} + run: | + echo "constraints: ${{ inputs.constraints }}" >> cabal.validate.project + + - name: Enable statically linked executables + if: inputs.static == 'true' + shell: ${{ inputs.shell }} + run: | + echo 'executable-static: true' >> cabal.validate.project + + # must happen before the main setup so the correct ghc is default + # hm, but what if setup-haskell needs to install ghcup? + - name: Install extra ghc for tests + if: inputs.extra_ghc != '' + shell: ${{ inputs.shell }} + run: | + ghcup install ghc ${{ inputs.extra_ghc }} + + - uses: haskell-actions/setup@v2 + id: setup-haskell + with: + ghc-version: ${{ inputs.ghc }} + cabal-version: 3.12.1.0 # see https://github.com/haskell/cabal/pull/10251 + ghcup-release-channel: https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-prereleases-0.0.8.yaml + + # See the following link for a breakdown of the following step + # https://github.com/haskell/actions/issues/7#issuecomment-745697160 + - uses: actions/cache@v4 + if: inputs.with_cache != 'false' + with: + # validate.sh uses a special build dir + path: | + ${{ steps.setup-haskell.outputs.cabal-store }} + dist-* + key: ${{ runner.os }}-${{ inputs.ghc }}-${{ github.sha }} + restore-keys: ${{ runner.os }}-${{ inputs.ghc }}- + + # The tool is not essential to the rest of the test suite. If + # hackage-repo-tool is not present, any test that requires it will + # be skipped. + # We want to keep this in the loop but we don't want to fail if + # hackage-repo-tool breaks or fails to support a newer GHC version. + - name: Install hackage-repo-tool + continue-on-error: true + shell: ${{ inputs.shell }} + run: | + cabal install --ignore-project hackage-repo-tool + + # Needed by cabal-testsuite/PackageTests/Configure/setup.test.hs + - name: "MAC: Install Autotools" + if: runner.os == 'macOS' + shell: ${{ inputs.shell }} + run: | + brew install automake + + # Needed by cabal-testsuite/PackageTests/Configure/setup.test.hs + - name: "WIN: Install Autotools" + if: runner.os == 'Windows' + shell: ${{ inputs.shell }} + run: | + /usr/bin/pacman --noconfirm -S autotools + + - name: Set validate inputs + shell: ${{ inputs.shell }} + run: | + FLAGS="$COMMON_FLAGS" + if [[ "${{ inputs.ghc }}" == "$GHC_FOR_SOLVER_BENCHMARKS" ]]; then + FLAGS="$FLAGS --solver-benchmarks" + fi + if [[ "${{ matrix.ghc }}" == "$GHC_FOR_COMPLETE_HACKAGE_TESTS" ]]; then + FLAGS="$FLAGS --complete-hackage-tests" + fi + echo "FLAGS=$FLAGS" >> "$GITHUB_ENV" + + - name: Validate print-config + shell: ${{ inputs.shell }} + run: | + sh validate.sh $FLAGS -s print-config + + - name: Validate print-tool-versions + shell: ${{ inputs.shell }} + run: | + sh validate.sh $FLAGS -s print-tool-versions + + - name: Canonicalize architecture + shell: ${{ inputs.shell }} + run: | + case ${{ runner.arch }} in + X86) arch=i386 ;; + X64) arch=x86_64 ;; + ARM64) arch=aarch64 ;; + *) echo "Unsupported architecture, please fix validate.yaml" 2>/dev/null; exit 1 ;; + esac + echo "CABAL_ARCH=$arch" >> "$GITHUB_ENV" diff --git a/.github/actions/validate-full/action.yml b/.github/actions/validate-full/action.yml new file mode 100644 index 00000000000..97cdd0850d5 --- /dev/null +++ b/.github/actions/validate-full/action.yml @@ -0,0 +1,145 @@ +name: Validate full +description: Run a full validate on a ghc version +inputs: + ghc: + description: ghc version to use + required: true + allow-newer: + description: allow-newer line + required: false + constraints: + description: constraints line + required: false + static: + description: whether to build statically + required: false + default: 'false' + shell: + description: shell to use + required: false + default: 'bash' + with_cache: + description: whether to instantiate cache + required: false + default: 'true' + +runs: + using: composite + steps: + - uses: ./.github/actions/cabal-setup + id: cabal-setup + with: + shell: ${{ inputs.shell }} + ghc: ${{ inputs.ghc }} + allow-newer: ${{ inputs.allow-newer }} + constraints: ${{ inputs.constraints }} + static: ${{ inputs.static }} + with_cache: ${{ inputs.with_cache }} + + - name: Validate build + shell: ${{ inputs.shell }} + run: | + echo ::group::Build + sh validate.sh $FLAGS -s build + + - name: Tar cabal head executable + if: matrix.ghc == env.GHC_FOR_RELEASE + shell: ${{ inputs.shell }} + run: | + echo ::group::Tar + CABAL_EXEC=$(cabal list-bin --builddir=dist-newstyle-validate-ghc-${{ matrix.ghc }} --project-file=cabal.validate.project cabal-install:exe:cabal) + # We have to tar the executable to preserve executable permissions + # see https://github.com/actions/upload-artifact/issues/38 + if [[ "${{ runner.os }}" == "Windows" ]]; then + # `cabal list-bin` gives us a windows path but tar needs the posix one + CABAL_EXEC=$(cygpath "$CABAL_EXEC") + fi + if [[ "${{ runner.os }}" == "macOS" ]]; then + # Workaround to avoid bsdtar corrupting the executable + # such that executing it after untar throws `cannot execute binary file` + # see https://github.com/actions/virtual-environments/issues/2619#issuecomment-788397841 + sudo /usr/sbin/purge + fi + DIR=$(dirname "$CABAL_EXEC") + FILE=$(basename "$CABAL_EXEC") + CABAL_EXEC_TAR="cabal-head-${{ runner.os }}-$CABAL_ARCH.tar.gz" + tar -czvf "$CABAL_EXEC_TAR" -C "$DIR" "$FILE" + echo "CABAL_EXEC_TAR=$CABAL_EXEC_TAR" >> "$GITHUB_ENV" + + # We upload the cabal executable built with the ghc used in the release for: + # - Reuse it in the dogfooding job (although we could use the cached build dir) + # - Make it available in the workflow to make easier testing it locally + - name: Upload cabal-install executable to workflow artifacts + if: inputs.ghc == env.GHC_FOR_RELEASE + uses: actions/upload-artifact@v4 + with: + name: cabal-${{ runner.os }}-${{ env.CABAL_ARCH }} + path: ${{ env.CABAL_EXEC_TAR }} + + # We want all the tests to be run even if one fails, but we want to fail the validate + # if any of them fail. It turns out that there is a way to get at the outcome of a step + # before `continue-on-error`` is applied, so the last step uses that. + # + # Note that we can't use filter syntax to look for any such failure, because the + # hackage-repo-tool install is also `continue-on-error` and its failure is legitimate + # (see the comment there). So the final step must list all of the tests, not that I expect + # any new ones to be added. + + - name: Validate lib-tests + id: lib-tests + continue-on-error: true + env: + # `rawSystemStdInOut reports text decoding errors` + # test does not find ghc without the full path in windows + GHCPATH: ${{ steps.setup-haskell.outputs.ghc-exe }} + shell: ${{ inputs.shell }} + run: | + echo ::group::Validate lib-tests + sh validate.sh $FLAGS -s lib-tests + + - name: Validate lib-suite + id: lib-suite + continue-on-error: true + shell: ${{ inputs.shell }} + run: | + echo ::group::Validate lib-suite + sh validate.sh $FLAGS -s lib-suite + + - name: Validate cli-tests + id: cli-tests + continue-on-error: true + shell: ${{ inputs.shell }} + run: | + echo ::group::Validate cli-tests + sh validate.sh $FLAGS -s cli-tests + + - name: Validate cli-suite + id: cli-suite + continue-on-error: true + shell: ${{ inputs.shell }} + run: | + echo ::group::Validate cli-suite + sh validate.sh $FLAGS -s cli-suite + + - name: Validate solver-benchmarks-tests + id: solver-benchmarks-tests + continue-on-error: true + if: "matrix.ghc == env.GHC_FOR_SOLVER_BENCHMARKS" + shell: ${{ inputs.shell }} + run: | + echo ::group::Validate solver-benchmarks-tests + sh validate.sh $FLAGS -s solver-benchmarks-tests + + - name: Validate solver-benchmarks-run + id: solver-benchmarks-run + continue-on-error: true + if: "matrix.ghc == env.GHC_FOR_SOLVER_BENCHMARKS" + shell: ${{ inputs.shell }} + run: | + echo ::group::Validate solver-benchmarks-run + sh validate.sh $FLAGS -s solver-benchmarks-run + + - name: Collect test results + if: steps.lib-tests.outcome == 'failure' || steps.lib-suite.outcome == 'failure' || steps.cli-tests.outcome == 'failure' || steps.cli-suite.outcome == 'failure' || steps.solver-benchmarks-tests.outcome == 'failure' || steps.solver-benchmarks-run.outcome == 'failure' + shell: ${{ inputs.shell }} + run: exit 1 diff --git a/.github/config.yml b/.github/config.yml new file mode 100644 index 00000000000..a96662b9cbf --- /dev/null +++ b/.github/config.yml @@ -0,0 +1,16 @@ +# all of these will get "GHC_" prepended +# the single quotes will be consumed by the JSON parser +# note: FOR_RELEASE must be an element of both FOR_VALIDATE and FOR_BOOTSTRAP! +FOR_RELEASE: '9.4.8' +FOR_SOLVER_BENCHMARKS: '${GHC_FOR_RELEASE}' +FOR_COMPLETE_HACKAGE_TESTS: '${GHC_FOR_RELEASE}' +# these will be decoded with fromJSON +# If you remove something from here, then add it to the old-ghcs job. +# Also a removed GHC from here means that we are actually dropping +# support, so the PR *must* have a changelog entry. +FOR_VALIDATE: '["9.10.1", "9.8.2", "9.6.6", "9.4.8", "9.2.8", "9.0.2", "8.10.7", "8.8.4"]' +## GHC 7.10.3 does not install on ubuntu-22.04 with ghcup. +## Older GHCs are not supported by ghcup in the first place. +FOR_VALIDATE_OLD: '["8.4.4", "8.2.2", "8.0.2"]' +FOR_BOOTSTRAP: '["9.8.2", "9.6.6", "9.4.8", "9.2.8", "9.0.2"]' +COMMON_FLAGS: '-j 2 -v' diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 9395720b417..b5d11fe65d3 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -49,25 +49,39 @@ on: required: false type: string -env: - # We choose a stable ghc version across all os's - # which will be used to do the next release - GHC_FOR_RELEASE: "9.4.8" - # Ideally we should use the version about to be released for hackage tests and benchmarks - GHC_FOR_SOLVER_BENCHMARKS: "9.4.8" - GHC_FOR_COMPLETE_HACKAGE_TESTS: "9.4.8" - COMMON_FLAGS: "-j 2 -v" +jobs: - # See https://github.com/haskell/cabal/blob/master/CONTRIBUTING.md#hackage-revisions - ALLOWNEWER: ${{ github.event.inputs.allow-newer }} - CONSTRAINTS: ${{ github.event.inputs.constraints }} + config: + runs-on: ubuntu-latest + # `matrix` can't access `env`, but it can access `outputs` from `needs` jobs. + # So we have to "export" some things here as job outputs. + # Oh, also the action documents a set-environment option that it doesn't honor. + outputs: + GHC_FOR_RELEASE: ${{ steps.conf.outputs['FOR_RELEASE'] }} + GHC_FOR_VALIDATE: ${{ steps.conf.outputs['FOR_VALIDATE'] }} + GHC_FOR_VALIDATE_OLD: ${{ steps.conf.outputs['FOR_VALIDATE_OLD'] }} + steps: + - uses: actions/checkout@v4 + + - uses: pietrobolcato/action-read-yaml@1.0.0 + id: conf + with: + config: ${{ github.workspace }}/.github/config.yml + + - run: | + # can't enumerate the keys of `outputs`, of course (Thanks, GitHub!) + # nor can I use a shell loop because GHA can't see the shell variable + echo "GHC_FOR_RELEASE=${{ steps.conf.outputs['FOR_RELEASE'] }}" >> "$GITHUB_ENV" + echo "GHC_FOR_SOLVER_BENCHMARKS=${{ steps.conf.outputs['FOR_SOLVER_BENCHMARKS'] }}" >> "$GITHUB_ENV" + echo "GHC_FOR_COMPLETE_HACKAGE_TESTS=${{ steps.conf.outputs['FOR_COMPLETE_HACKAGE_TESTS'] }}" >> "$GITHUB_ENV" + echo "GHC_FOR_VALIDATE=${{ steps.conf.outputs['FOR_VALIDATE'] }}" >> "$GITHUB_ENV" + echo "GHC_FOR_VALIDATE_OLD=${{ steps.conf.outputs['FOR_VALIDATE_OLD'] }}" >> "$GITHUB_ENV" + echo "COMMON_FLAGS=${{ steps.conf.outputs['COMMON_FLAGS'] }}" >> "$GITHUB_ENV" -jobs: validate: name: Validate ${{ matrix.sys.os }} ghc-${{ matrix.ghc }} runs-on: ${{ matrix.sys.os }} - outputs: - GHC_FOR_RELEASE: ${{ format('["{0}"]', env.GHC_FOR_RELEASE) }} + needs: config strategy: fail-fast: false matrix: @@ -75,20 +89,7 @@ jobs: - { os: windows-latest, shell: "C:/msys64/usr/bin/bash.exe -e {0}" } - { os: ubuntu-22.04, shell: bash } - { os: macos-latest, shell: bash } - # If you remove something from here, then add it to the old-ghcs job. - # Also a removed GHC from here means that we are actually dropping - # support, so the PR *must* have a changelog entry. - ghc: - [ - "9.10.1", - "9.8.2", - "9.6.6", - "9.4.8", - "9.2.8", - "9.0.2", - "8.10.7", - "8.8.4", - ] + ghc: ${{ fromJSON(needs.config.outputs.GHC_FOR_VALIDATE) }} exclude: # Throws fatal "cabal-tests.exe: fd:8: hGetLine: end of file" exception # even with --io-manager=native @@ -116,157 +117,17 @@ jobs: - sys: { os: macos-latest, shell: bash } ghc: "8.8.4" - defaults: - run: - shell: ${{ matrix.sys.shell }} steps: - - name: Work around XDG directories existence (haskell-actions/setup#62) - if: runner.os == 'macOS' - run: | - rm -rf ~/.config/cabal - rm -rf ~/.cache/cabal - - - name: "WIN: Setup TMP environment variable" - if: runner.os == 'Windows' - run: | - echo "TMP=${{ runner.temp }}" >> "$GITHUB_ENV" - - - uses: actions/checkout@v4 - - # See https://github.com/haskell/cabal/blob/master/CONTRIBUTING.md#hackage-revisions - - name: Add manually supplied allow-newer - if: github.event_name == 'workflow_dispatch' && github.event.inputs.allow-newer != '' - run: | - echo "allow-newer: ${{ github.event.inputs.allow-newer }}" >> cabal.validate.project - - - name: Add manually supplied constraints - if: github.event_name == 'workflow_dispatch' && github.event.inputs.constraints != '' - run: | - echo "constraints: ${{ github.event.inputs.constraints }}" >> cabal.validate.project - - - uses: haskell-actions/setup@v2 - id: setup-haskell - with: - ghc-version: ${{ matrix.ghc }} - cabal-version: 3.12.1.0 # see https://github.com/haskell/cabal/pull/10251 - ghcup-release-channel: https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-prereleases-0.0.8.yaml - - # See the following link for a breakdown of the following step - # https://github.com/haskell/actions/issues/7#issuecomment-745697160 - - uses: actions/cache@v4 - with: - # validate.sh uses a special build dir - path: | - ${{ steps.setup-haskell.outputs.cabal-store }} - dist-* - key: ${{ runner.os }}-${{ matrix.ghc }}-${{ github.sha }} - restore-keys: ${{ runner.os }}-${{ matrix.ghc }}- - - # The tool is not essential to the rest of the test suite. If - # hackage-repo-tool is not present, any test that requires it will - # be skipped. - # We want to keep this in the loop but we don't want to fail if - # hackage-repo-tool breaks or fails to support a newer GHC version. - - name: Install hackage-repo-tool - continue-on-error: true - run: cabal install --ignore-project hackage-repo-tool - - # Needed by cabal-testsuite/PackageTests/Configure/setup.test.hs - - name: "MAC: Install Autotools" - if: runner.os == 'macOS' - run: brew install automake - - # Needed by cabal-testsuite/PackageTests/Configure/setup.test.hs - - name: "WIN: Install Autotools" - if: runner.os == 'Windows' - run: /usr/bin/pacman --noconfirm -S autotools - - - name: Set validate inputs - run: | - FLAGS="${{ env.COMMON_FLAGS }}" - if [[ "${{ matrix.ghc }}" == "${{ env.GHC_FOR_SOLVER_BENCHMARKS }}" ]]; then - FLAGS="$FLAGS --solver-benchmarks" - fi - if [[ "${{ matrix.ghc }}" == "${{ env.GHC_FOR_COMPLETE_HACKAGE_TESTS }}" ]]; then - FLAGS="$FLAGS --complete-hackage-tests" - fi - echo "FLAGS=$FLAGS" >> "$GITHUB_ENV" + - uses: actions/checkout@v4 - - name: Validate print-config - run: sh validate.sh $FLAGS -s print-config - - - name: Validate print-tool-versions - run: sh validate.sh $FLAGS -s print-tool-versions - - - name: Validate build - run: sh validate.sh $FLAGS -s build - - - name: Canonicalize architecture - run: | - case ${{ runner.arch }} in - X86) arch=i386 ;; - X64) arch=x86_64 ;; - ARM64) arch=aarch64 ;; - *) echo "Unsupported architecture, please fix validate.yaml" 2>/dev/null; exit 1 ;; - esac - echo "CABAL_ARCH=$arch" >> "$GITHUB_ENV" - - - name: Tar cabal head executable - if: matrix.ghc == env.GHC_FOR_RELEASE - run: | - CABAL_EXEC=$(cabal list-bin --builddir=dist-newstyle-validate-ghc-${{ matrix.ghc }} --project-file=cabal.validate.project cabal-install:exe:cabal) - # We have to tar the executable to preserve executable permissions - # see https://github.com/actions/upload-artifact/issues/38 - if [[ "${{ runner.os }}" == "Windows" ]]; then - # `cabal list-bin` gives us a windows path but tar needs the posix one - CABAL_EXEC=$(cygpath "$CABAL_EXEC") - fi - if [[ "${{ runner.os }}" == "macOS" ]]; then - # Workaround to avoid bsdtar corrupts the executable - # so executing it after untar throws `cannot execute binary file` - # see https://github.com/actions/virtual-environments/issues/2619#issuecomment-788397841 - sudo /usr/sbin/purge - fi - DIR=$(dirname "$CABAL_EXEC") - FILE=$(basename "$CABAL_EXEC") - CABAL_EXEC_TAR="cabal-head-${{ runner.os }}-$CABAL_ARCH.tar.gz" - tar -czvf "$CABAL_EXEC_TAR" -C "$DIR" "$FILE" - echo "CABAL_EXEC_TAR=$CABAL_EXEC_TAR" >> "$GITHUB_ENV" - - # We upload the cabal executable built with the ghc used in the release for: - # - Reuse it in the dogfooding job (although we could use the cached build dir) - # - Make it available in the workflow to make easier testing it locally - - name: Upload cabal-install executable to workflow artifacts - if: matrix.ghc == env.GHC_FOR_RELEASE - uses: actions/upload-artifact@v4 - with: - name: cabal-${{ runner.os }}-${{ env.CABAL_ARCH }} - path: ${{ env.CABAL_EXEC_TAR }} - - - name: Validate tests - env: - # `rawSystemStdInOut reports text decoding errors` - # test does not find ghc without the full path in windows - GHCPATH: ${{ steps.setup-haskell.outputs.ghc-exe }} - run: | - set +e - rc=0 - tests="lib-tests lib-suite cli-tests cli-suite" - if [ "${{ matrix.ghc }}" = "${{ env.GHC_FOR_SOLVER_BENCHMARKS }}" ]; then - tests="$tests solver-benchmarks-tests solver-benchmarks-run" - fi - for test in $tests; do - echo Validate "$test" - sh validate.sh $FLAGS -s "$test" || rc=1 - echo End "$test" - done - exit $rc - # The above ensures all the tests get run, for a single platform+ghc. - # Trying to ensure they run for *all* combinations but still fail - # at the end seems to be extremely difficult at best. It's doable, - # but it requires a continuously growing stack of conditions and - # one possibly nightmarish final conditional. 'fail-fast' gets us - # partway there, at least, but is still imperfect. + # N.B. Local actions must start with "./" to distinguish them from remote actions, which + # start with "X/" where X is an organization (which can't be ".") + - uses: ./.github/actions/validate-full + with: + shell: ${{ matrix.sys.shell }} + ghc: ${{ matrix.ghc }} + allow-newer: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.allow_newer || '' }} + constraints: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.constraints || '' }} validate-old-ghcs: name: Validate old ghcs ${{ matrix.extra-ghc }} @@ -275,65 +136,41 @@ jobs: strategy: matrix: - extra-ghc: - ["8.4.4", "8.2.2", "8.0.2"] - ## GHC 7.10.3 does not install on ubuntu-22.04 with ghcup. - ## Older GHCs are not supported by ghcup in the first place. + extra-ghc: ${{ fromJSON(needs.config.outputs.GHC_FOR_VALIDATE_OLD) }} fail-fast: false steps: - - uses: actions/checkout@v4 - - name: Install prerequisites for old GHCs run: | sudo apt-get update sudo apt-get install libncurses5 libtinfo5 - - name: Install extra compiler - run: ghcup install ghc ${{ matrix.extra-ghc }} - - - name: GHCup logs - if: always() - run: cat /usr/local/.ghcup/logs/* + - uses: actions/checkout@v4 - - name: Install primary compiler - uses: haskell-actions/setup@v2 - id: setup-haskell + - uses: ./.github/actions/cabal-setup with: - ghc-version: ${{ env.GHC_FOR_RELEASE }} - cabal-version: latest + ghc: ${{ env.GHC_FOR_RELEASE }} + extra_ghc: ${{ matrix.extra-ghc }} - name: GHC versions run: | ghc --version "ghc-${{ matrix.extra-ghc }}" --version - # As we are reusing the cached build dir from the previous step - # the generated artifacts are available here, - # including the cabal executable and the test suite - - uses: actions/cache@v4 - with: - path: | - ${{ steps.setup-haskell.outputs.cabal-store }} - dist-* - key: ${{ runner.os }}-${{ env.GHC_FOR_RELEASE }}-${{ github.sha }} - restore-keys: ${{ runner.os }}-${{ env.GHC_FOR_RELEASE }}- - - name: Validate build id: build - run: sh validate.sh ${{ env.COMMON_FLAGS }} -s build + run: | + sh validate.sh $COMMON_FLAGS -s build - name: "Validate lib-suite-extras --extra-hc ghc-${{ matrix.extra-ghc }}" - env: - EXTRA_GHC: ghc-${{ matrix.extra-ghc }} - run: sh validate.sh ${{ env.COMMON_FLAGS }} --lib-only -s lib-suite-extras --extra-hc "${{ env.EXTRA_GHC }}" - # See the comment above about running all tests but still failing if one - # of them does; it also applies here. + run: | + sh validate.sh $COMMON_FLAGS --lib-only -s lib-suite-extras --extra-hc "ghc-${{ matrix.extra-ghc }}" build-alpine: name: Build statically linked using alpine runs-on: ubuntu-latest container: "alpine:3.19" + needs: config steps: - name: Install extra dependencies shell: sh @@ -345,52 +182,35 @@ jobs: - uses: actions/checkout@v4 - # See https://github.com/haskell/cabal/blob/master/CONTRIBUTING.md#hackage-revisions - - name: Manually supplied constraints/allow-newer - if: github.event_name == 'workflow_dispatch' - run: | - echo "allow-newer: ${ALLOWNEWER}" >> cabal.validate.project - echo "constraints: ${CONSTRAINTS}" >> cabal.validate.project - - - uses: haskell-actions/setup@v2 - id: setup-haskell - with: - ghc-version: ${{ env.GHC_FOR_RELEASE }} - cabal-version: latest # latest is mandatory for cabal-testsuite, see https://github.com/haskell/cabal/issues/8133 - - # See the following link for a breakdown of the following step - # https://github.com/haskell/actions/issues/7#issuecomment-745697160 - - uses: actions/cache@v4 + - uses: ./.github/actions/cabal-setup with: - # validate.sh uses a special build dir - path: | - ${{ steps.setup-haskell.outputs.cabal-store }} - dist-* - key: ${{ runner.os }}-${{ env.GHC_FOR_RELEASE }}-${{ github.sha }} - restore-keys: ${{ runner.os }}-${{ env.GHC_FOR_RELEASE }}- - - - name: Enable statically linked executables - run: | - echo 'executable-static: true' >> cabal.validate.project + ghc: ${{ env.GHC_FOR_RELEASE }} + static: 'true' + allow-newer: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.allow_newer || '' }} + constraints: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.constraints || '' }} - name: Build + # $FLAGS is set by the cabal-setup action (perhaps it should be an output instead) run: sh validate.sh $FLAGS -s build - name: Tar cabal head executable run: | - CABAL_EXEC=$(cabal list-bin --builddir=dist-newstyle-validate-ghc-${{ env.GHC_FOR_RELEASE }} --project-file=cabal.validate.project cabal-install:exe:cabal) + ::group::dump env + env + ::endgroup:: + CABAL_EXEC=$(cabal list-bin --builddir=dist-newstyle-validate-ghc-$GHC_FOR_RELEASE --project-file=cabal.validate.project cabal-install:exe:cabal) # We have to tar the executable to preserve executable permissions # see https://github.com/actions/upload-artifact/issues/38 DIR=$(dirname "$CABAL_EXEC") FILE=$(basename "$CABAL_EXEC") - CABAL_EXEC_TAR="cabal-head-${{ runner.os }}-static-x86_64.tar.gz" + CABAL_EXEC_TAR="cabal-head-${{ runner.os }}-static-$CABAL_ARCH.tar.gz" tar -czvf "$CABAL_EXEC_TAR" -C "$DIR" "$FILE" echo "CABAL_EXEC_TAR=$CABAL_EXEC_TAR" >> "$GITHUB_ENV" - name: Upload cabal-install executable to workflow artifacts uses: actions/upload-artifact@v4 with: - name: cabal-${{ runner.os }}-static-x86_64 + name: cabal-${{ runner.os }}-static-${{ env.CABAL_ARCH }} path: ${{ env.CABAL_EXEC_TAR }} # The previous jobs use a released version of cabal to build cabal HEAD itself @@ -409,41 +229,21 @@ jobs: # We only use one ghc version the used one for the next release (defined at top of the workflow) # We need to build an array dynamically to inject the appropiate env var in a previous job, # see https://docs.github.com/en/actions/learn-github-actions/expressions#fromjson - ghc: ${{ fromJSON (needs.validate.outputs.GHC_FOR_RELEASE) }} + ghc: ${{ fromJSON (needs.config.outputs.GHC_FOR_RELEASE) }} defaults: run: shell: ${{ matrix.sys.shell }} steps: - # TODO: make a reusable action for this - - name: Canonicalize architecture - run: | - case ${{ runner.arch }} in - X86) arch=i386 ;; - X64) arch=x86_64 ;; - ARM64) arch=aarch64 ;; - *) echo "Unsupported architecture" 2>/dev/null; exit 1 ;; - esac - echo "CABAL_ARCH=$arch" >> "$GITHUB_ENV" - - - name: "MAC: Work around XDG directories existence (haskell-actions/setup#62)" - if: runner.os == 'macOS' - run: | - rm -rf ~/.config/cabal - rm -rf ~/.cache/cabal - - - name: "WIN: Setup TMP environment variable" - if: runner.os == 'Windows' - run: | - echo "TMP=${{ runner.temp }}" >> "$GITHUB_ENV" - - uses: actions/checkout@v4 - - uses: haskell-actions/setup@v2 - id: setup-haskell + - uses: ./.github/actions/cabal-setup with: - ghc-version: ${{ matrix.ghc }} - cabal-version: latest # default, we are not using it in this job + ghc: ${{ matrix.ghc }} + shell: ${{ matrix.sys.shell }} + allow-newer: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.allow_newer || '' }} + constraints: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.constraints || '' }} + with_cache: 'false' - name: Download cabal executable from workflow artifacts uses: actions/download-artifact@v4 @@ -452,15 +252,18 @@ jobs: path: cabal-head - name: Untar the cabal executable - run: tar -xzf "./cabal-head/cabal-head-${{ runner.os }}-$CABAL_ARCH.tar.gz" -C cabal-head + run: | + tar -xzf "./cabal-head/cabal-head-${{ runner.os }}-$CABAL_ARCH.tar.gz" -C cabal-head - name: print-config using cabal HEAD - run: sh validate.sh ${{ env.COMMON_FLAGS }} --with-cabal ./cabal-head/cabal -s print-config + run: | + sh validate.sh $COMMON_FLAGS --with-cabal ./cabal-head/cabal -s print-config - # We dont use cache to force a build with a fresh store dir and build dir + # We don't use cache to force a build with a fresh store dir and build dir # This way we check cabal can build all its dependencies - name: Build using cabal HEAD - run: sh validate.sh ${{ env.COMMON_FLAGS }} --with-cabal ./cabal-head/cabal -s build + run: | + sh validate.sh $COMMON_FLAGS --with-cabal ./cabal-head/cabal -s build prerelease-head: name: Create a GitHub prerelease with the binary artifacts @@ -504,7 +307,6 @@ jobs: path: binaries - run: | - # bash-ism, but we forced bash above cd binaries for f in cabal-*; do mv "$f" "cabal-lts-${f##cabal-}" @@ -517,6 +319,7 @@ jobs: uses: softprops/action-gh-release@v2 with: tag_name: cabal-lts-head + target_commitish: '3.12' prerelease: true files: binaries/cabal-* diff --git a/cabal-testsuite/PackageTests/BuildDeps/SameDepsAllRound/lemon.hs b/cabal-testsuite/PackageTests/BuildDeps/SameDepsAllRound/lemon.hs index a775b158cc1..7f3da431021 100644 --- a/cabal-testsuite/PackageTests/BuildDeps/SameDepsAllRound/lemon.hs +++ b/cabal-testsuite/PackageTests/BuildDeps/SameDepsAllRound/lemon.hs @@ -1,6 +1,8 @@ import qualified Data.ByteString.Char8 as C import Text.PrettyPrint +deliberate syntax error for testing + main = do putStrLn (render (text "foo")) let text = "lemon"