Merge pull request #308 from liskin/release-infra

Automate and document releasing to Hackage + couple cleanups
This commit is contained in:
Tomáš Janoušek 2021-07-25 02:17:21 +02:00 committed by GitHub
commit 05aeef0dc2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 234 additions and 47 deletions

View File

@ -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 }}

View File

@ -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
@ -171,8 +181,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 }}

View File

@ -59,58 +59,59 @@
## Release Procedures
When the time comes to release another version of XMonad and Contrib...
When the time comes to release another version of xmonad and xmonad-contrib:
1. Create a release branch (e.g., `release-0.XX`).
1. Update the version number in all the `*.cabal` files and let the CI
verify that it all builds together.
This will allow you to separate the release process from main
development. Changes you make on this branch will be merged back
into `master` as one of the last steps.
2. Review documentation files and make sure they are accurate:
2. Update the version number in the `*.cabal` files and verify
dependencies and documentation. This includes the `tested-with:`
field.
- [`README.md`](README.md)
- [`CHANGES.md`](CHANGES.md)
- [`INSTALL.md`](INSTALL.md)
- [`man/xmonad.1.markdown.in`](man/xmonad.1.markdown.in)
- [haddocks](https://xmonad.github.io/xmonad-docs/)
3. Use the [packdeps][] tool to ensure you have the dependency
versions correct. If you need to update the version of a
dependency then you should rebuild and retest.
If the manpage changes, wait for the CI to rebuild the rendered outputs.
4. Review documentation files and make sure they are accurate:
3. Check dependency bounds. In particular, [packdeps][] can be used to check
if any new versions are excluded by the upper bounds specified.
Also, make sure that `tested-with:` covers several recent releases of
GHC, and that `.github/workflows/stack.yml` tests with several recent
revisions of [Stackage][] LTS.
- `README.md`
- `CHANGES.md`
- and the `example-config.hs` in the `xmonad-testing` repo
4. Create a release on GitHub:
5. Generate the manpage:
- https://github.com/xmonad/xmonad/releases/new
- https://github.com/xmonad/xmonad-contrib/releases/new
* `cabal configure` with the `-fgeneratemanpage` flag
* Build the project
* Run the `generatemanpage` tool from the top level of this repo
* Review the man page: `man -l man/xmonad.1`
CI will upload a release candidate to Hackage. Check again that
everything looks good. To publish a final release, run the CI workflow
once again with the correct version number:
6. Tag the repository with the release version (e.g., `v0.13`)
- https://github.com/xmonad/xmonad/actions/workflows/haskell-ci.yml
- https://github.com/xmonad/xmonad-contrib/actions/workflows/haskell-ci.yml
7. Build the project tarballs (`cabal sdist`)
See [haskell-ci-hackage.patch][] for details about the release infrastructure.
8. Upload the packages to Hackage (`cabal upload`)
5. Update the website:
9. Merge the release branches into `master`
- Post a [new release announcement][web-announce]
- Check install instructions, guided tour, keybindings cheat sheet, …
10. Update the website:
7. Post announcement to:
* Generate and push haddocks with `xmonad-web/gen-docs.sh`
- [XMonad mailing list](https://mail.haskell.org/mailman/listinfo/xmonad)
- [Haskell Cafe](https://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe)
- [Haskell Discourse](https://discourse.haskell.org/)
* Check that `tour.html` and `intro.html` are up to date, and
mention all core bindings
See [old announcements][old-announce] for inspiration.
11. Update the topic for the IRC channel (`#xmonad`)
12. Send the `announce-0.XX.txt` file to:
- XMonad mailing list
- Haskell Cafe
[packdeps]: http://hackage.haskell.org/package/packdeps
[packdeps]: https://hackage.haskell.org/package/packdeps
[Stackage]: https://www.stackage.org/
[haskell-ci-hackage.patch]: .github/workflows/haskell-ci-hackage.patch
[web-announce]: https://github.com/xmonad/xmonad-web/tree/gh-pages/news/_posts
[old-announce]: https://github.com/xmonad/xmonad-web/tree/55614349421ebafaef4a47424fcb16efa80ff768
## Website and Other Accounts

View File

@ -5,6 +5,9 @@ apt:
libxrandr-dev
libxss-dev
github-patches:
.github/workflows/haskell-ci-hackage.patch
raw-project
package xmonad
flags: +pedantic

View File

@ -39,7 +39,7 @@ import XMonad.Operations
import XMonad.ManageHook
import qualified XMonad.StackSet as W
import Data.Bits ((.|.))
import Data.Default
import Data.Default.Class
import Data.Monoid
import qualified Data.Map as M
import System.Exit

View File

@ -43,7 +43,7 @@ import Control.Monad.State
import Control.Monad.Reader
import Data.Semigroup
import Data.Traversable (for)
import Data.Default
import Data.Default.Class
import System.FilePath
import System.IO
import System.Info

View File

@ -35,10 +35,11 @@ build-type: Simple
extra-source-files: README.md
CHANGES.md
CONFIG
CONTRIBUTING.md
INSTALL.md
MAINTAINERS.md
STYLE
tests/*.hs
tests/Properties/*.hs
tests/Properties/Layout/*.hs
TUTORIAL.md
man/xmonad.1.markdown
man/xmonad.1
man/xmonad.1.html
@ -71,7 +72,7 @@ library
build-depends: base >= 4.9 && < 5
, X11 >= 1.10 && < 1.11
, containers
, data-default
, data-default-class
, directory
, filepath
, mtl
@ -79,7 +80,6 @@ library
, setlocale
, transformers >= 0.3
, unix
, utf8-string >= 0.3 && < 1.1
ghc-options: -funbox-strict-fields -Wall -Wno-unused-do-bind
-- Keep this in sync with the oldest version in 'tested-with'
@ -91,7 +91,7 @@ library
executable xmonad
main-is: Main.hs
build-depends: base, X11, mtl, unix, xmonad
build-depends: base, xmonad
ghc-options: -Wall -Wno-unused-do-bind
-- Keep this in sync with the oldest version in 'tested-with'