Skip to content

build

build #1483

Workflow file for this run

name: build
on:
push: null
schedule:
- cron: 59 14 * * 5
pull_request: null
jobs:
build:
name: Build and test
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-22.04
- macos-12 # Intel
- macos-13-xlarge # Apple silicon
- windows-2022
ghc-version:
- "8.8"
- "8.10"
- "9.0"
- "9.2"
- "9.4"
exclude:
- os: macos-12
ghc-version: "8.10"
- os: macos-12
ghc-version: "9.0"
- os: macos-12
ghc-version: "9.2"
- os: macos-13-xlarge
ghc-version: "8.8"
- os: macos-13-xlarge
ghc-version: "8.10"
- os: macos-13-xlarge
ghc-version: "9.0"
- os: macos-13-xlarge
ghc-version: "9.2"
- os: windows-2022
ghc-version: "8.10"
- os: windows-2022
ghc-version: "9.0"
# GHC 9.4 uses LLVM on Windows which breaks some dependencies:
- os: windows-2022
ghc-version: "9.4"
env:
STACK_YAML: stack-ghc-${{ matrix.ghc-version }}.yaml
steps:
- uses: actions/checkout@v4
with:
lfs: true
- uses: dahlia/actions/setup-yq@main
- name: Cache Stack files (non-Windows)
if: "!startsWith(matrix.os, 'windows-')"
uses: actions/cache@v4
with:
path: |
~/.cabal/packages
~/.cabal/store
~/.stack
key: stack-${{ matrix.os }}-ghc-${{ matrix.ghc-version }}
- name: Cache Stack files (Windows)
if: "startsWith(matrix.os, 'windows-')"
uses: actions/cache@v4
with:
path: |
%APPDATA%\cabal\packages
%APPDATA%\cabal\store
%APPDATA%\stack
key: stack-${{ matrix.os }}-ghc-${{ matrix.version }}
- name: Install Haskell Stack (if not installed)
shell: bash
run: |
if ! command -v stack > /dev/null; then
curl -sSL https://get.haskellstack.org/ | sh
fi
- name: Set up resolver
shell: bash
run: |
# Try 3 times because this sometimes fails due to network error
# on GitHub Actions.
stack setup || stack setup || stack setup
- name: Check version
if: >-
github.event_name != 'pull_request' &&
startsWith(github.ref, 'refs/tags/')
shell: bash
run: |
pkg_ver="$(stack query locals seonbi version)"
echo "Package version: $pkg_ver"
tag_ver="${GITHUB_REF:10}"
echo "Git tag version: $tag_ver"
[[ "$tag_ver" = "$pkg_ver" ]]
! grep -i "to be released" CHANGES.md
- name: Resolve dependencies
run: stack install --test --only-dependencies
- name: Build
run: stack build --test
- name: Test
run: stack test
- name: Package source distribution
if: startsWith(matrix.os, 'ubuntu-')
run: |
# Hackage disallows -Werror
sed -i 's/^ *- -Werror$//g' package.yaml
stack sdist --ignore-check || true
mkdir -p /tmp/sdist
mv "$(stack path --dist-dir)"/*.tar.gz /tmp/sdist/
ls -al /tmp/sdist
- name: Save source distribution
if: startsWith(matrix.os, 'ubuntu-')
uses: actions/upload-artifact@v4
with:
name: sdist-${{ matrix.os }}-ghc-${{ matrix.ghc-version }}
path: /tmp/sdist
- name: Build docs
if: >-
startsWith(matrix.os, 'ubuntu-') &&
matrix.ghc-version == '9.2'
shell: bash
run: |
curl -L -o /tmp/pandoc.deb \
https://github.com/jgm/pandoc/releases/download/2.14.2/pandoc-2.14.2-1-amd64.deb
sudo dpkg -i /tmp/pandoc.deb
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys CC86BB64
sudo add-apt-repository ppa:rmescandon/yq
sudo apt update
sudo apt-get install -y yq
bash scripts/haddock-prologue/build.sh
- name: Copy docs
if: >-
startsWith(matrix.os, 'ubuntu-') &&
matrix.ghc-version == '9.2'
shell: bash
run: cp -r "$(stack path --dist-dir)/doc/html/seonbi" _docs
- name: Save docs
if: >-
startsWith(matrix.os, 'ubuntu-') &&
matrix.ghc-version == '9.2'
uses: actions/upload-artifact@v4
with:
name: docs
path: _docs
if-no-files-found: error
- name: Build using -fembed-dictionary
run: stack build --flag seonbi:embed-dictionary
- name: Copy required DLLs
if: startsWith(matrix.os, 'windows-')
shell: pwsh
run: .\scripts\Bundle-RequiredDlls.ps1 -Verbose
- name: Copy executable binaries
shell: bash
run: |
ls -al "$(stack path --local-install-root)/bin"
cp -r "$(stack path --local-install-root)/bin" _bin
ls -al _bin
- name: Compress executable binaries
if: "startsWith(matrix.os, 'ubuntu-')"
uses: crazy-max/ghaction-upx@v3
with:
files: _bin/seonbi*
args: "-9"
- name: Save executable binaries
uses: actions/upload-artifact@v4
with:
name: binaries-${{ matrix.os }}-ghc-${{ matrix.ghc-version }}
path: _bin
if-no-files-found: error
deno:
name: Deno client library
needs:
- build
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-22.04
- macos-12 # Intel
- macos-13-xlarge # Apple silicon
- windows-2022
steps:
- uses: actions/checkout@v4
- uses: denoland/setup-deno@v1
with:
deno-version: v1.x
- if: matrix.os != 'windows-2022'
uses: actions/download-artifact@v4
with:
name: binaries-${{ matrix.os }}-ghc-9.4
path: ${{ runner.temp }}/bin
- if: matrix.os == 'windows-2022'
uses: actions/download-artifact@v4
with:
name: binaries-${{ matrix.os }}-ghc-9.2
path: ${{ runner.temp }}/bin
- run: chmod +x ${{ runner.temp }}/bin/seonbi*
if: "!startsWith(matrix.os, 'windows-')"
- working-directory: scripts/deno/
env:
SEONBI_API: >-
${{ runner.temp }}/bin/seonbi-api${{
startsWith(matrix.os, 'windows-') && '.exe' || ''
}}
run: '"$SEONBI_API" --help'
if: "!startsWith(matrix.os, 'windows-')"
- working-directory: scripts/deno/
env:
SEONBI_API: >-
${{ runner.temp }}/bin/seonbi-api${{
startsWith(matrix.os, 'windows-') && '.exe' || ''
}}
shell: cmd
run: '%SEONBI_API% --help'
if: "startsWith(matrix.os, 'windows-')"
- name: Test (manual install)
working-directory: scripts/deno/
env:
SEONBI_API: >-
${{ runner.temp }}/bin/seonbi-api${{
startsWith(matrix.os, 'windows-') && '.exe' || ''
}}
SEONBI_API_PORT: ${{ startsWith(matrix.os, 'macos-') && 8800 || 3800 }}
DENO_JOBS: 1
run: >-
deno test
--check
--allow-env=SEONBI_API,SEONBI_API_PORT,SEONBI_API_URL
--allow-net=127.0.0.1:${{ env.SEONBI_API_PORT }}
--allow-run
--unstable-process
- name: Test (auto install)
working-directory: scripts/deno/
env:
SEONBI_API_PORT: ${{ startsWith(matrix.os, 'macos-') && 8800 || 3800 }}
DENO_JOBS: 1
run: >-
deno test
--check
--allow-env=SEONBI_API,SEONBI_API_PORT,SEONBI_API_URL,TMPDIR,TEMP
--allow-read
--allow-write
--allow-net=127.0.0.1:${{ env.SEONBI_API_PORT }},github.com,github-releases.githubusercontent.com,dahlia.github.io,hongminhee.org
--allow-run
--unstable-process
- name: Test (hosted server)
working-directory: scripts/deno/
env:
SEONBI_API_URL: https://seonbi.fly.dev/
SEONBI_API: >-
${{ runner.temp }}/bin/seonbi-api${{
startsWith(matrix.os, 'windows-') && '.exe' || ''
}}
SEONBI_API_PORT: ${{ startsWith(matrix.os, 'macos-') && 8800 || 3800 }}
DENO_JOBS: 1
run: >-
deno test
--check
--allow-env=SEONBI_API,SEONBI_API_PORT
--allow-net=seonbi.fly.dev,127.0.0.1:${{ env.SEONBI_API_PORT }}
--allow-run
--unstable-process
image:
name: Docker image
runs-on: ubuntu-22.04
env:
DOCKERHUB_IMAGE_NAME: seonbi
outputs:
image-ghcr: ghcr.io/${{ github.repository }}/bin@${{ steps.push-image.outputs.digest }}
image-dockerhub: docker.io/${{ vars.DOCKERHUB_USERNAME }}/${{ env.DOCKERHUB_IMAGE_NAME }}@${{ steps.push-image.outputs.digest }}
steps:
- uses: actions/checkout@v4
with:
lfs: true
- uses: docker/setup-buildx-action@v3
- if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ github.token }}
- if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
username: ${{ vars.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- id: values
run: |
if [[ "$GITHUB_EVENT_NAME" = "pull_request" ]]; then
echo tag="git-$GITHUB_SHA" >> "$GITHUB_OUTPUT"
elif [[ "$GITHUB_REF" = "refs/heads/main" ]]; then
echo tag=latest >> "$GITHUB_OUTPUT"
else
echo tag="$GITHUB_REF_NAME" >> "$GITHUB_OUTPUT"
fi
if [[ "$GITHUB_REF_TYPE" = tag ]]; then
echo labels=org.opencontainers.image.version="$GITHUB_REF_NAME" \
>> "$GITHUB_OUTPUT"
else
echo labels= >> "$GITHUB_OUTPUT"
fi
- id: push-image
uses: docker/build-push-action@v6
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
labels: |
org.opencontainers.image.revision=${{ github.sha }}
org.opencontainers.image.url=${{ github.event.repository.html_url }}
${{ steps.values.outputs.labels }}
tags: |
ghcr.io/${{ github.repository }}/bin:${{ steps.values.outputs.tag }}
${{ vars.DOCKERHUB_USERNAME }}/${{ env.DOCKERHUB_IMAGE_NAME }}:${{ steps.values.outputs.tag }}
provenance: false # https://community.fly.io/t/deploying-to-fly-via-github-action-failing/10171/33
fly:
name: Deploy seonbi-api to Fly.io
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
needs:
- image
env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
IMAGE: ${{ needs.image.outputs.image-ghcr }}
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: superfly/flyctl-actions/setup-flyctl@master
- run: |
curl -L -o /tmp/subtoml \
https://github.com/pbzweihander/subtoml-rs/releases/download/v0.1.0/subtoml
chmod +x /tmp/subtoml
/tmp/subtoml \
-i fly.toml \
-o fly.toml \
build.image="$IMAGE"
cat fly.toml
- run: flyctl deploy --remote-only
binaries:
name: Package executable binaries
needs:
- build
- image
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: binaries-macos-13-xlarge-ghc-9.4
path: /tmp/binaries-macos-arm64
- uses: actions/download-artifact@v4
with:
name: binaries-macos-12-ghc-9.4
path: /tmp/binaries-macos-x86_64
- uses: actions/download-artifact@v4
with:
name: binaries-windows-2022-ghc-9.2
path: /tmp/binaries-windows
- run: |
set -e
mkdir -p /tmp/dists
# Linux
docker pull "$IMAGE"
mkdir -p /tmp/binaries-linux
docker run -i "$IMAGE" cat /usr/local/bin/seonbi \
> /tmp/binaries-linux/seonbi
docker run -i "$IMAGE" cat /usr/local/bin/seonbi-api \
> /tmp/binaries-linux/seonbi-api
pushd /tmp/binaries-linux
chmod +x *
cp "$GITHUB_WORKSPACE/"{LICENSE,README.md,CHANGES.md} ./
tar cvfj /tmp/dists/seonbi.linux-x86_64.tar.bz2 *
popd
# macOS (Apple silicon)
pushd /tmp/binaries-macos-arm64
chmod +x *
cp "$GITHUB_WORKSPACE/"{LICENSE,README.md,CHANGES.md} ./
tar cvfj /tmp/dists/seonbi.macos-arm64.tar.bz2 *
popd
# macOS (Intel)
pushd /tmp/binaries-macos-x86_64
chmod +x *
cp "$GITHUB_WORKSPACE/"{LICENSE,README.md,CHANGES.md} ./
tar cvfj /tmp/dists/seonbi.macos-x86_64.tar.bz2 *
popd
# Windows
pushd /tmp/binaries-windows
cp "$GITHUB_WORKSPACE/"{LICENSE,README.md,CHANGES.md} ./
zip /tmp/dists/seonbi.win64.zip *
popd
env:
IMAGE: ${{ needs.image.outputs.image-ghcr }}
- uses: actions/upload-artifact@v4
with:
name: dists-untagged
path: /tmp/dists
release:
name: Release dist files
needs:
- build
- binaries
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: sdist-ubuntu-22.04-ghc-9.4
path: /tmp/sdist
- uses: actions/download-artifact@v4
with:
name: dists-untagged
path: /tmp/dists
- id: extract-changelog
uses: dahlia/submark@e21a51982ee1c5ca798edf9b3c25c299f910d606
with:
input-file: CHANGES.md
heading-level: 2
heading-title-text: Version ${{ github.ref_name }}
ignore-case: true
omit-heading: true
- run: |
pushd /tmp/dists
for file in ./*; do
mv "$file" "${file/seonbi/seonbi-$GITHUB_REF_NAME}"
done
- uses: actions/upload-artifact@v4
with:
name: dists
path: |
/tmp/sdist/*
/tmp/dists/*
- if: github.ref_type == 'tag'
uses: ncipollo/release-action@v1
with:
artifactErrorsFailBuild: true
artifacts: /tmp/sdist/*,/tmp/dists/*
bodyFile: ${{ steps.extract-changelog.outputs.output-file }}
name: Seonbi ${{ github.ref_name }}
- env:
HACKAGE_API_KEY: ${{ secrets.HACKAGE_API_KEY }}
run: |
for file in /tmp/sdist/*; do
curl \
-H "Authorization: X-ApiKey $HACKAGE_API_KEY" \
-F package=@"$file" \
https://hackage.haskell.org/packages/
done
demo:
name: Deploy demo app
needs:
- binaries
if: >-
github.event_name != 'pull_request' &&
github.ref == 'refs/heads/main'
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: dists-untagged
path: /tmp/dists
- uses: actions/download-artifact@v4
with:
name: docs
path: /tmp/docs
# Generates a showcase SVG image
- run: |
mkdir "$HOME/bin/"
pushd "$HOME/bin/"
tar xvfj /tmp/dists/seonbi.linux-x86_64.tar.bz2
popd
sudo apt-get install -y xqilla
pushd scripts/showcase-svg/
make build/showcase.svg SEONBI="$HOME/bin/seonbi"
popd
- run: |
pushd /tmp
curl -L -o elm.gz \
https://github.com/elm/compiler/releases/download/0.19.1/binary-for-linux-64-bit.gz
gunzip elm.gz
chmod +x elm
popd
git config --global user.name "$GITHUB_ACTOR"
git config --global user.email "[email protected]"
git init /tmp/html
pushd demo/
/tmp/elm make --optimize --output=/tmp/html/index.html src/Demo.elm
# GitHub Corners <https://github.com/tholman/github-corners>
sed -Ezi 's|\s*</body>\s*</html>\s*$||' /tmp/html/index.html
{
cat github-corner.html
echo '</body></html>'
} >> /tmp/html/index.html
popd
# Showcase SVG
cp scripts/showcase-svg/build/showcase.svg /tmp/html/
# Deno client library
mkdir /tmp/html/deno
rm -rf /tmp/html/deno/latest
cp -r scripts/deno /tmp/html/deno/latest
if [[ "$GITHUB_REF" = refs/tags/* ]]; then
rmf -rf /tmp/html/deno/"${GITHUB_REF:10}"
cp -r scripts/deno /tmp/html/deno/"${GITHUB_REF:10}"
fi
pushd /tmp/html
git add deno
popd
# Docs
cp -r /tmp/docs /tmp/html/docs
cd /tmp/html
git add index.html
git add showcase.svg
git add docs/
# Bleeding-edge binaries
mkdir dists
mv /tmp/dists dists/latest
git add dists
git commit -m 'Demo app and docs'
git branch --move gh-pages
auth="$GITHUB_ACTOR:${{ secrets.GH_TOKEN }}"
git remote add origin \
"https://[email protected]/$GITHUB_REPOSITORY.git"
git push -f origin gh-pages