Skip to content

Wrap releases

Wrap releases #5375

Workflow file for this run

# This workflow takes care of creating release archives for the
# GAP distribution. It is run for all PR and branch pushes as usual,
# but also on tags named `vX.Y.Z` with X, Y, Z numbers.
#
# For builds triggered by a tag, the tag is turned into a GitHub release and
# the produced archives are attached to that.
name: "Wrap releases"
on:
workflow_dispatch:
pull_request:
push:
tags:
- v[1-9]+.[0-9]+.[0-9] # allow v1.2.3
- v[1-9]+.[0-9]+.[0-9]-* # allow v1.2.3-beta3 etc.
branches:
- master
- stable-*
schedule:
# Every day at 3:33 AM UTC
- cron: '33 3 * * *'
concurrency:
# group by workflow and ref; the last slightly strange component ensures that for pull
# requests, we limit to 1 concurrent job, but for the master branch we don't
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.ref != 'refs/heads/master' || github.run_number }}
# Cancel intermediate builds, but only if it is a pull request build.
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
env:
NO_COVERAGE: 1
jobs:
tools:
name: "Validate release scripts"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: "Set up Python"
uses: actions/setup-python@v5
with:
python-version: 3.11
- name: "Install some python packages"
run: |
python -m pip install -r dev/releases/requirements.txt
python -m pip install black isort mypy pytest
- name: "Check code formatting"
run: python -m black --check --diff dev/releases
- name: "Check imports"
run: python -m isort --check --profile black dev/releases
#- name: "Validate types"
# run: python -m mypy --disallow-untyped-calls --disallow-untyped-defs dev/releases/*.py
#- name: "Run tests"
# run: python -m pytest tools/tests/dev/releases*.py -vv
unix:
name: "Create Unix archives and data"
needs: tools
# Don't run this twice on PRs for branches pushed to the same repository
if: ${{ !(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) }}
runs-on: ubuntu-latest
outputs:
gap-build-version: ${{ steps.get-build.outputs.name }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
# When an annotated tag is pushed, then for some reason we don't see it
# in this action; instead an unannotated tag with the same name is
# present, we resolve this by force-fetching tags.
# But we first fetch tags from gap-system/gap, so that our scripts should
# know about all of the 'usual' tags.
# Only then do we fetch tags from the current fork, which will overwrite
# any of those from gap-system/gap that conflict.
- name: "Force fetch tags"
run: |
git fetch https://github.com/gap-system/gap --tags --force
git fetch --tags --force
- name: "Install autoconf 2.72" # for compatibility with GCC 14 & clang versions
run: |
wget https://ftp.gnu.org/gnu/autoconf/autoconf-2.72.tar.xz
tar xvf autoconf-2.72.tar.xz
cd autoconf-2.72
./configure
make
sudo make install
- name: "Set up Python"
uses: actions/setup-python@v5
with:
python-version: 3.11
- name: "Install some python packages"
run: |
python -m pip install -r dev/releases/requirements.txt
- name: "Install latex"
run: |
packages=(
texlive-latex-base
texlive-latex-recommended
texlive-latex-extra
texlive-fonts-recommended
)
sudo apt-get update
sudo apt-get install --no-install-recommends "${packages[@]}"
- name: "Configure GAP"
run: dev/ci-configure-gap.sh
- name: "Build GAP"
run: dev/ci-build-gap.sh
- name: "Record the GAP build version"
id: get-build
run: |
BUILD=`head -1 cnf/GAP-VERSION-FILE | cut -d ' ' -f3`
echo "steps.get-build.outputs.name = ${BUILD}"
echo "name=${BUILD}" >> $GITHUB_OUTPUT
- name: "Make archives"
run: python -u ./dev/releases/make_archives.py
- name: "Test building GAP from the primary release archive"
run: |
mkdir -p test-gap-tarball
pushd test-gap-tarball
tar xvf ../tmp/gap-${{ steps.get-build.outputs.name }}.tar.gz
cd gap*
# test building GAP
./configure --prefix=/tmp/gapprefix
make -j8
popd
- name: "Test 'make install' from the primary release archive"
run: |
pushd test-gap-tarball/gap*
../../dev/ci.sh testmakeinstall
popd
# Upload the main GAP .tar.gz file (which includes packages).
#
# Warning: the result is a single .zip file (so things are compressed twice).
- name: "Upload GAP tarball"
uses: actions/upload-artifact@v4
with:
if-no-files-found: error
name: gap
path: tmp/gap-${{ steps.get-build.outputs.name }}.tar.gz
retention-days: 1
# Always upload metadata, and keep longer, since it is much smaller.
- name: "Upload JSON metadata"
uses: actions/upload-artifact@v4
with:
if-no-files-found: error
name: "JSON metadata"
path: tmp/*json.gz
retention-days: 7
- name: "Make GitHub release"
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
run: python -u ./dev/releases/make_github_release.py ${GITHUB_REF#refs/tags/} tmp/
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
cygwin:
name: "Create Windows x86_64 installer"
needs: unix
runs-on: windows-2019
env:
CHERE_INVOKING: 1
GAP_VERSION: ${{ needs.unix.outputs.gap-build-version }}
defaults:
run:
shell: bash
strategy:
fail-fast: false
steps:
# The GAP to be wrapped is put into gap-$GAP_VERSION/
# The gap-windows script requires the GAP directory to be named this way.
# Download the artifact -- for an actual release, this contains the
# exact same tarball as was uploaded to the release as an asset
- name: "Download GAP archive from previous job"
uses: actions/download-artifact@v4
with:
name: gap
- name: "Extract the GAP release tarball"
run: |
tar -zxf gap-${GAP_VERSION}.tar.gz
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: "Clone the Windows installer maker scripts"
uses: actions/checkout@v4
with:
repository: gap-system/gap-windows
ref: main
path: gap-windows
- uses: gap-actions/setup-cygwin@v1
# Currently, the gap-windows/release_gap.sh script wraps the GAP
# contained in gap-${GAP_VERSION}, and outputs its installer to
# gap-windows/Output/gap-${GAP_VERSION}-$ARCH.exe
#
# TODO:
# * Investigate how to speed this up. e.g. if we don't need to compile
# GAP's manuals then could we perhaps avoid installing TeXLive?
# * Investigate splitting release_gap.sh into multiple scripts so that
# this big step can be split up into multiple steps
- name: "Compile GAP and its packages, and create the installer"
shell: C:\cygwin64\bin\bash.exe --login --norc -o igncr '{0}'
run: |
cd ${GITHUB_WORKSPACE}/gap-windows
bash release_gap.sh
# compute the sha256sum, taking care to avoid a trailing newline
NAME=Output/gap-${{ env.GAP_VERSION }}-x86_64.exe
printf "%s" "$(sha256sum $NAME | cut -c1-64)" >$NAME.sha256
env:
ARCH: x86_64
# Artifacts live for 1 day, i.e. until the next cron job runs.
- name: "Upload the installer as an artifact"
if: ${{ github.event_name == 'schedule' }}
uses: actions/upload-artifact@v4
with:
if-no-files-found: error
name: gap-${{ env.GAP_VERSION }}-x86_64.exe
path: gap-windows/Output/gap-${{ env.GAP_VERSION }}-x86_64.exe
retention-days: 1
- name: "Upload the installer to tag"
uses: softprops/action-gh-release@v2
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
with:
files: |
gap-windows/Output/gap-${{ env.GAP_VERSION }}-x86_64.exe
gap-windows/Output/gap-${{ env.GAP_VERSION }}-x86_64.exe.sha256
# The following job is duplicated in CI.yml - keep the two in sync.
# (except for their different 'needs' components).
slack-notification:
name: Send Slack notification on status change
needs:
- unix
- cygwin
if: ${{ always() && github.event_name != 'pull_request' && github.repository == 'gap-system/gap' }}
runs-on: ubuntu-latest
steps:
- name: Get branch name
id: get-branch
run: echo "branch=${GITHUB_REF#refs/*/}" >> $GITHUB_OUTPUT
- name: Determine whether CI status changed
uses: gap-actions/should-i-notify-action@v1
id: should_notify
with:
branch: ${{ steps.get-branch.outputs.branch }}
needs_context: ${{ toJson(needs) }}
github_token: ${{ secrets.GITHUB_TOKEN }}
notify_on_changed_status: true
- name: Send slack notification
uses: act10ns/slack@v2
if: ${{ steps.should_notify.outputs.should_send_message == 'yes' }}
with:
status: ${{ steps.should_notify.outputs.current_status }}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}