diff --git a/.github/workflows/haskell-ci-hackage.patch b/.github/workflows/haskell-ci-hackage.patch new file mode 100644 index 0000000000..e7b8702982 --- /dev/null +++ b/.github/workflows/haskell-ci-hackage.patch @@ -0,0 +1,115 @@ +Piggy-back on the haskell-ci workflow for automatic releases to Hackage. + +This extends the workflow with two additional triggers: + + * When a release is created on GitHub, a candidate release is uploaded to + Hackage and docs are submitted for it as Hackage can't build them itself + (https://github.com/haskell/hackage-server/issues/925). + + * To make a final release, the workflow can be triggered manually by entering + the correct version number matching the version in the cabal file. This is + here because promoting the candidate on Hackage discards the uploaded docs + (https://github.com/haskell/hackage-server/issues/70). + +The automation uses a special Hackage user: https://hackage.haskell.org/user/xmonad +and each repo (X11, xmonad, xmonad-contrib) has its own HACKAGE_API_KEY token +set in GitHub repository secrets. + +--- .github/workflows/haskell-ci.yml.orig ++++ .github/workflows/haskell-ci.yml +@@ -14,8 +14,17 @@ + # + name: Haskell-CI + on: +- - push +- - pull_request ++ push: ++ pull_request: ++ release: ++ types: ++ - published ++ workflow_dispatch: ++ inputs: ++ version: ++ # releases to Hackage are final and cannot be reverted, thus require ++ # manual entry of version as a poor man's mistake avoidance ++ description: version (must match version in cabal file) + jobs: + linux: + name: Haskell-CI - Linux - ${{ matrix.compiler }} +@@ -28,6 +37,7 @@ + include: + - compiler: ghc-9.0.1 + allow-failure: false ++ upload: true + - compiler: ghc-8.10.4 + allow-failure: false + - compiler: ghc-8.8.4 +@@ -171,8 +181,66 @@ + ${CABAL} -vnormal check + - name: haddock + run: | +- $CABAL v2-haddock $ARG_COMPILER --with-haddock $HADDOCK $ARG_TESTS $ARG_BENCH all ++ $CABAL v2-haddock $ARG_COMPILER --with-haddock $HADDOCK $ARG_TESTS $ARG_BENCH --haddock-for-hackage --builddir $GITHUB_WORKSPACE/haddock all + - name: unconstrained build + run: | + rm -f cabal.project.local + $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks all ++ - name: upload artifacts (sdist) ++ if: matrix.upload ++ uses: actions/upload-artifact@v2 ++ with: ++ path: ${{ github.workspace }}/sdist/*.tar.gz ++ - name: upload artifacts (haddock) ++ if: matrix.upload ++ uses: actions/upload-artifact@v2 ++ with: ++ path: ${{ github.workspace }}/haddock/*-docs.tar.gz ++ - name: hackage upload (candidate) ++ if: matrix.upload && github.event_name == 'release' ++ run: | ++ set -ex ++ PACKAGE_VERSION="${PACKAGE_VERSION#v}" ++ curl \ ++ --silent --show-error --fail \ ++ --header "Accept: text/plain" \ ++ --header "Authorization: X-ApiKey $HACKAGE_API_KEY" \ ++ --form package=@"${GITHUB_WORKSPACE}/sdist/${PACKAGE_NAME}-${PACKAGE_VERSION}.tar.gz" \ ++ https://hackage.haskell.org/packages/candidates/ ++ curl \ ++ --silent --show-error --fail \ ++ -X PUT \ ++ --header "Accept: text/plain" \ ++ --header "Authorization: X-ApiKey $HACKAGE_API_KEY" \ ++ --header "Content-Type: application/x-tar" \ ++ --header "Content-Encoding: gzip" \ ++ --data-binary @"${GITHUB_WORKSPACE}/haddock/${PACKAGE_NAME}-${PACKAGE_VERSION}-docs.tar.gz" \ ++ https://hackage.haskell.org/package/${PACKAGE_NAME}-${PACKAGE_VERSION}/candidate/docs ++ env: ++ HACKAGE_API_KEY: ${{ secrets.HACKAGE_API_KEY }} ++ PACKAGE_NAME: ${{ github.event.repository.name }} ++ PACKAGE_VERSION: ${{ github.event.release.tag_name }} ++ - name: hackage upload (release) ++ if: matrix.upload && github.event_name == 'workflow_dispatch' ++ run: | ++ set -ex ++ PACKAGE_VERSION="${PACKAGE_VERSION#v}" ++ curl \ ++ --silent --show-error --fail \ ++ --header "Accept: text/plain" \ ++ --header "Authorization: X-ApiKey $HACKAGE_API_KEY" \ ++ --form package=@"${GITHUB_WORKSPACE}/sdist/${PACKAGE_NAME}-${PACKAGE_VERSION}.tar.gz" \ ++ https://hackage.haskell.org/packages/ ++ curl \ ++ --silent --show-error --fail \ ++ -X PUT \ ++ --header "Accept: text/plain" \ ++ --header "Authorization: X-ApiKey $HACKAGE_API_KEY" \ ++ --header "Content-Type: application/x-tar" \ ++ --header "Content-Encoding: gzip" \ ++ --data-binary @"${GITHUB_WORKSPACE}/haddock/${PACKAGE_NAME}-${PACKAGE_VERSION}-docs.tar.gz" \ ++ https://hackage.haskell.org/package/${PACKAGE_NAME}-${PACKAGE_VERSION}/docs ++ env: ++ HACKAGE_API_KEY: ${{ secrets.HACKAGE_API_KEY }} ++ PACKAGE_NAME: ${{ github.event.repository.name }} ++ PACKAGE_VERSION: ${{ github.event.inputs.version }} diff --git a/.github/workflows/haskell-ci.yml b/.github/workflows/haskell-ci.yml index 618bae502e..0364c51165 100644 --- a/.github/workflows/haskell-ci.yml +++ b/.github/workflows/haskell-ci.yml @@ -14,8 +14,17 @@ # name: Haskell-CI on: - - push - - pull_request + push: + pull_request: + release: + types: + - published + workflow_dispatch: + inputs: + version: + # releases to Hackage are final and cannot be reverted, thus require + # manual entry of version as a poor man's mistake avoidance + description: version (must match version in cabal file) jobs: linux: name: Haskell-CI - Linux - ${{ matrix.compiler }} @@ -28,6 +37,7 @@ jobs: include: - compiler: ghc-9.0.1 allow-failure: false + upload: true - compiler: ghc-8.10.4 allow-failure: false - compiler: ghc-8.8.4 @@ -193,8 +203,66 @@ jobs: ${CABAL} -vnormal check - name: haddock run: | - $CABAL v2-haddock $ARG_COMPILER --with-haddock $HADDOCK $ARG_TESTS $ARG_BENCH all + $CABAL v2-haddock $ARG_COMPILER --with-haddock $HADDOCK $ARG_TESTS $ARG_BENCH --haddock-for-hackage --builddir $GITHUB_WORKSPACE/haddock all - name: unconstrained build run: | rm -f cabal.project.local $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks all + - name: upload artifacts (sdist) + if: matrix.upload + uses: actions/upload-artifact@v2 + with: + path: ${{ github.workspace }}/sdist/*.tar.gz + - name: upload artifacts (haddock) + if: matrix.upload + uses: actions/upload-artifact@v2 + with: + path: ${{ github.workspace }}/haddock/*-docs.tar.gz + - name: hackage upload (candidate) + if: matrix.upload && github.event_name == 'release' + run: | + set -ex + PACKAGE_VERSION="${PACKAGE_VERSION#v}" + curl \ + --silent --show-error --fail \ + --header "Accept: text/plain" \ + --header "Authorization: X-ApiKey $HACKAGE_API_KEY" \ + --form package=@"${GITHUB_WORKSPACE}/sdist/${PACKAGE_NAME}-${PACKAGE_VERSION}.tar.gz" \ + https://hackage.haskell.org/packages/candidates/ + curl \ + --silent --show-error --fail \ + -X PUT \ + --header "Accept: text/plain" \ + --header "Authorization: X-ApiKey $HACKAGE_API_KEY" \ + --header "Content-Type: application/x-tar" \ + --header "Content-Encoding: gzip" \ + --data-binary @"${GITHUB_WORKSPACE}/haddock/${PACKAGE_NAME}-${PACKAGE_VERSION}-docs.tar.gz" \ + https://hackage.haskell.org/package/${PACKAGE_NAME}-${PACKAGE_VERSION}/candidate/docs + env: + HACKAGE_API_KEY: ${{ secrets.HACKAGE_API_KEY }} + PACKAGE_NAME: ${{ github.event.repository.name }} + PACKAGE_VERSION: ${{ github.event.release.tag_name }} + - name: hackage upload (release) + if: matrix.upload && github.event_name == 'workflow_dispatch' + run: | + set -ex + PACKAGE_VERSION="${PACKAGE_VERSION#v}" + curl \ + --silent --show-error --fail \ + --header "Accept: text/plain" \ + --header "Authorization: X-ApiKey $HACKAGE_API_KEY" \ + --form package=@"${GITHUB_WORKSPACE}/sdist/${PACKAGE_NAME}-${PACKAGE_VERSION}.tar.gz" \ + https://hackage.haskell.org/packages/ + curl \ + --silent --show-error --fail \ + -X PUT \ + --header "Accept: text/plain" \ + --header "Authorization: X-ApiKey $HACKAGE_API_KEY" \ + --header "Content-Type: application/x-tar" \ + --header "Content-Encoding: gzip" \ + --data-binary @"${GITHUB_WORKSPACE}/haddock/${PACKAGE_NAME}-${PACKAGE_VERSION}-docs.tar.gz" \ + https://hackage.haskell.org/package/${PACKAGE_NAME}-${PACKAGE_VERSION}/docs + env: + HACKAGE_API_KEY: ${{ secrets.HACKAGE_API_KEY }} + PACKAGE_NAME: ${{ github.event.repository.name }} + PACKAGE_VERSION: ${{ github.event.inputs.version }} diff --git a/cabal.haskell-ci b/cabal.haskell-ci index 77cb4c8750..edfa3f2a77 100644 --- a/cabal.haskell-ci +++ b/cabal.haskell-ci @@ -9,6 +9,9 @@ apt: hlint: True hlint-yaml: .hlint.yaml +github-patches: + .github/workflows/haskell-ci-hackage.patch + raw-project optimization: False package xmonad-contrib