Piggy-back on the haskell-ci workflow for automatic releases to Hackage. This extends the workflow with two additional triggers: * When the Haskell-CI workflow is triggered manually with a non-empty version input (matching the version in the cabal file), 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). Note that promoting the candidate on Hackage discards the uploaded docs (https://github.com/haskell/hackage-server/issues/70). Don't do that. * When a release is created on GitHub, a final release is uploaded to Hackage and docs are submitted for it. 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,15 @@ # name: Haskell-CI on: - - push - - pull_request + push: + pull_request: + release: + types: + - published + workflow_dispatch: + inputs: + version: + description: candidate version (must match version in cabal file) jobs: linux: name: Haskell-CI - Linux - ${{ matrix.compiler }} @@ -31,6 +38,7 @@ compilerVersion: 9.0.2 setup-method: ghcup allow-failure: false + upload: true - compiler: ghc-8.10.7 compilerKind: ghc compilerVersion: 8.10.7 @@ -237,7 +237,7 @@ ${CABAL} -vnormal check - name: haddock run: | - $CABAL v2-haddock --disable-documentation $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 @@ -248,3 +248,75 @@ with: key: ${{ runner.os }}-${{ matrix.compiler }}-${{ github.sha }} path: ~/.cabal/store + - name: upload artifacts (sdist) + if: matrix.upload + uses: actions/upload-artifact@v3 + with: + path: ${{ github.workspace }}/sdist/*.tar.gz + - name: upload artifacts (haddock) + if: matrix.upload + uses: actions/upload-artifact@v3 + with: + path: ${{ github.workspace }}/haddock/*-docs.tar.gz + - name: hackage upload (candidate) + if: matrix.upload && github.event_name == 'workflow_dispatch' && github.event.inputs.version != '' + shell: bash + run: | + set -ex + PACKAGE_VERSION="${PACKAGE_VERSION#v}" + res=$( + curl \ + --silent --show-error --output /dev/stderr --write-out '%{http_code}' \ + --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/ + ) + [[ $res == 2?? ]] # TODO: --fail-with-body once curl 7.76.0 is available + res=$( + curl \ + --silent --show-error --output /dev/stderr --write-out '%{http_code}' \ + -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 + ) + [[ $res == 2?? ]] + env: + HACKAGE_API_KEY: ${{ secrets.HACKAGE_API_KEY }} + PACKAGE_NAME: ${{ github.event.repository.name }} + PACKAGE_VERSION: ${{ github.event.inputs.version }} + - name: hackage upload (release) + if: matrix.upload && github.event_name == 'release' + shell: bash + run: | + set -ex + PACKAGE_VERSION="${PACKAGE_VERSION#v}" + res=$( + curl \ + --silent --show-error --output /dev/stderr --write-out '%{http_code}' \ + --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/ + ) + [[ $res == 2?? ]] # TODO: --fail-with-body once curl 7.76.0 is available + res=$( + curl \ + --silent --show-error --output /dev/stderr --write-out '%{http_code}' \ + -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 + ) + [[ $res == 2?? ]] + env: + HACKAGE_API_KEY: ${{ secrets.HACKAGE_API_KEY }} + PACKAGE_NAME: ${{ github.event.repository.name }} + PACKAGE_VERSION: ${{ github.event.release.tag_name }}