Skip to content

Commit

Permalink
first cut at API checking
Browse files Browse the repository at this point in the history
Cabal-syntax and Cabal only; I assume cabal-install-solver is not
a public API.
  • Loading branch information
geekosaur committed Aug 21, 2024
1 parent 34bef80 commit d09f251
Show file tree
Hide file tree
Showing 5 changed files with 19,188 additions and 0 deletions.
102 changes: 102 additions & 0 deletions .github/workflows/check-api.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
name: Check API

on:
push:
paths-ignore:
- "doc/**"
- "**/README.md"
- "CONTRIBUTING.md"
branches:
- master
pull_request:
paths-ignore:
- "doc/**"
- "**/README.md"
- "CONTRIBUTING.md"
release:
types:
- created
workflow_call:

jobs:
check-api:
name: Check API using ${{ matrix.sys.os }} ghc-${{ matrix.ghc }}
runs-on: ${{ matrix.sys.os }}
strategy:
matrix:
# we check API only on one platform and ghc release, since it shouldn't
# vary elsewhere and the API tracer is sensitive to both
sys:
- { os: ubuntu-latest }
ghc:
[
# print-api only supports a small subset of ghc versions
"9.10.1",
]

steps:

- uses: actions/checkout@v4

- 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

# I was going to use the canned action, but it only supports a single package and reinstalls the same binary each time
- name: Install print-api
run: |
wget -q https://github.com/Kleidukos/print-api/releases/download/v0.1.0.1/print-api-0.1.0.1-Linux-static-${{ matrix.ghc }}-x86_64.tar.gz
tar -xzvf print-api-0.1.0.1-Linux-static-${{ matrix.ghc }}-x86_64.tar.gz
chmod +x print-api
# print-api needs environment files. It also doesn't make a lot of sense to use the cached builds, sadly,
# since they're special in different ways (bootstrap and validate) and we want a vanilla build. And there
# isn't enough cache space to make a third cache, even though this is a very limited build.
- name: Build Cabal with environment files
run: cabal build Cabal-syntax Cabal --write-ghc-environment-files=always

- name: Generate Cabal-syntax and Cabal APIs
run: |
./print-api --package-name Cabal-syntax > Cabal-syntax-${{ matrix.ghc }}-${{ matrix.sys.os }}.api
./print-api --package-name Cabal > Cabal-${{ matrix.ghc }}-${{ matrix.sys.os }}.api
# upload the new API records as artifacts, since there's no guarantee that a contributor could produce
# them (wrong platform or ghc version). This must happen _before_ we check the API, because the
# point is to have them available on API mismatch so they can be updated.
- uses: actions/upload-artifact@v4
with:
name: Cabal-api
path: '*.api'

- name: Check Cabal-syntax and Cabal APIs
run: |
rc=0
if diff -c Cabal-syntax/Cabal-syntax-${{ matrix.ghc }}-${{ matrix.sys.os }}.api Cabal-syntax-${{ matrix.ghc }}-${{ matrix.sys.os }}.api >api.tmp; then
:
else
echo "Cabal-syntax API changed"
if [ $(wc -l < api.tmp) -lt 50 ]; then
cat api.tmp
else
echo Diff too large for GitHub viewer
fi
rc=1
fi
if diff -c Cabal/Cabal-${{ matrix.ghc }}-${{ matrix.sys.os }}.api Cabal-${{ matrix.ghc }}-${{ matrix.sys.os }}.api >api.tmp; then
:
else
echo "Cabal API changed"
if [ $(wc -l < api.tmp) -lt 50 ]; then
cat api.tmp
else
echo Diff too large for GitHub viewer
fi
rc=1
fi
if [ $rc -ne 0 ]; then
echo "The new APIs are in the artifact uploaded in the previous step."
exit $rc
fi
27 changes: 27 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,33 @@ We use automated whitespace convention checking. Violations can be fixed by
running [fix-whitespace](https://hackage.haskell.org/package/fix-whitespace). If
you push a fix of a whitespace violation, please do so in a _separate commit_.

API Changes and Check API job
-----------------------------

The `Check API` job tests the `Cabal` and `Cabal-syntax` packages for API changes.
It's useful to indicate when a changelog is needed and which PRs aren't appropriate
for backports.

If the `Check API` job fails, you will find in its build artifacts (at the bottom
of the "upload artifacts" step, immediately before the actual API check) a ZIP file
containing the new API records. You can download this and replace the existing API
descriptions, which can be found in the package top level directories, with `.api`
suffixes. Generating them locally is possible with the [check-api tool](https://github.com/Kleidukos/print-api), but
the API dump contains information that is dependent on the platform and GHC version
and so is not guaranteed to produce the same result as the CI job does.

If you do wish to generate a local API record, install [`print-api`](https://github.com/Kleidukos/print-api/releases/tag/v0.1.0.1) and
run it on the `Cabal` and `Cabal-syntax` packages, from the top level directory of
the Cabal repo:

make generate-api

The resulting `Cabal-syntax.api` and `Cabal.api` files can then be compared to the
ones in the `Cabal-syntax` and `Cabal` package directories. Note that different
compiler versions and different architectures will alter the output. It is not
expected that different Linux distributions will, but you may need to use the static
build if you aren't using Ubuntu 22.04.

Other Conventions
-----------------

Expand Down
Loading

0 comments on commit d09f251

Please sign in to comment.