Skip to content

Merge pull request #5493 from unisonweb/24-12-05-add-todo-watch #2

Merge pull request #5493 from unisonweb/24-12-05-add-todo-watch

Merge pull request #5493 from unisonweb/24-12-05-add-todo-watch #2

Workflow file for this run

name: CI
defaults:
run:
shell: bash
on:
# Run on the post-merge result of every PR commit
pull_request:
# Build on the pre-merge result of every branch commit
push:
workflow_dispatch:
env:
## Some version numbers that are used during CI
ormolu_version: 0.7.2.0
jit_version: "@unison/internal/releases/0.0.25"
runtime_tests_version: "@unison/runtime-tests/releases/0.0.1"
## Some cached directories
# a temp path for caching a built `ucm`
ucm_local_bin: ucm-local-bin
# a temp path for caching generated jit sources
jit_src_scheme: unison-jit-src/scheme-libs/racket
jit_dist: unison-jit-dist
# a codebase path for caching a codebase generated by `unison-src/builtin-tests/interpreter-tests.md`
runtime_tests_codebase: "~/.cache/unisonlanguage/runtime-tests.unison"
# locations of some files that will indicate whether we need to re-run certain steps
transcript_test_results: transcript-test-results
interpreter_test_results: interpreter-test-results
## afaik, the jit sources are generated in a platform-independent way, so we choose one platform to generate them on.
jit_generator_os: ubuntu-20.04
jobs:
ormolu:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- name: Get changed files
uses: tj-actions/changed-files@v44
with:
# globs copied from default settings for run-ormolu
files: |
**/*.hs
**/*.hs-boot
separator: "\n"
- uses: haskell-actions/run-ormolu@v15
with:
version: ${{ env.ormolu_version }}
mode: inplace
pattern: ${{ steps.changed-files.outputs.all_changed_files }}
- name: apply formatting changes
uses: stefanzweifel/git-auto-commit-action@v5
# Only try to commit formatting changes if we're running within the repo containing the PR,
# and not on a protected branch.
# The job doesn't have permission to push back to contributor forks on contributor PRs.
if: |
always()
&& !github.ref_protected
&& github.event.pull_request.base.repo.full_name == github.event.pull_request.head.repo.full_name
with:
commit_message: automatically run ormolu
build-ucm:
name: build ucm
runs-on: ${{ matrix.os }}
strategy:
# Run each build to completion, regardless of if any have failed
fail-fast: false
matrix:
os:
# While iterating on this file, you can disable one or more of these to speed things up
- ubuntu-20.04
- macOS-13
- windows-2019
# - windows-2022
steps:
- uses: actions/checkout@v4
- name: tweak environment
id: tweak-environment
run: |
ucm_local_bin="${RUNNER_TEMP//\\//}/${ucm_local_bin}"
echo "ucm_local_bin=$ucm_local_bin" >> $GITHUB_ENV
if [[ ${{runner.os}} = "Windows" ]]; then
echo "ucm=$ucm_local_bin/unison.exe" >> $GITHUB_ENV
echo "transcripts=$ucm_local_bin/transcripts.exe" >> $GITHUB_ENV
else
echo "ucm=$ucm_local_bin/unison" >> $GITHUB_ENV
echo "transcripts=$ucm_local_bin/transcripts" >> $GITHUB_ENV
fi
- name: cache ucm binaries
id: cache-ucm-binaries
uses: actions/cache@v4
with:
path: ${{env.ucm_local_bin}}
key: ucm-${{ matrix.os }}-${{ hashFiles('**/stack.yaml', '**/package.yaml', '**/*.hs', '**/unison-cli-integration/integrationtests/IntegrationTests/*')}}
# added the integration test dependencies here as if they were source, for simplicity
- name: restore stack caches
if: steps.cache-ucm-binaries.outputs.cache-hit != 'true'
id: restore-stack-caches
uses: unisonweb/actions/stack/cache/restore@main
with:
cache-prefix: ci
- name: install stack
if: steps.cache-ucm-binaries.outputs.cache-hit != 'true'
uses: unisonweb/actions/stack/install@main
with:
stack-version: 2.15.5
# Build deps, then build local code. Splitting it into two steps just allows us to see how much time each step
# takes.
- name: build dependencies
if: steps.cache-ucm-binaries.outputs.cache-hit != 'true'
# Run up to 5 times in a row before giving up.
# It's very unlikely that our build-dependencies step will fail on most builds,
# so if it fails its almost certainly due to a race condition on the Windows
# file-system API that stack runs into. Since any successful packages are
# cached within a single build, it should get further along on each re-start
# and should hopefully finish!
run: |
stack --version
tries=1
if [[ ${{matrix.os}} = "windows-"* ]]; then
tries=5
fi
for (( i = 0; i < $tries; i++ )); do
stack build --fast --only-dependencies --test --bench && break;
done
- name: build
if: steps.cache-ucm-binaries.outputs.cache-hit != 'true'
run: |
stack build \
--fast \
--test \
--no-run-tests \
--local-bin-path ${{env.ucm_local_bin}} \
--copy-bins
# The unison-cli test requires a git user.
- name: set git user info
if: steps.cache-ucm-binaries.outputs.cache-hit != 'true'
run: |
git config --global user.name "GitHub Actions"
git config --global user.email "actions@github.com"
# Run each test suite (tests and transcripts)
- name: unison-cli test
if: steps.cache-ucm-binaries.outputs.cache-hit != 'true'
run: stack build --fast --test unison-cli
- name: unison-core tests
if: steps.cache-ucm-binaries.outputs.cache-hit != 'true'
run: stack build --fast --test unison-core
- name: unison-parser-typechecker tests
if: steps.cache-ucm-binaries.outputs.cache-hit != 'true'
run: stack build --fast --test unison-parser-typechecker
- name: unison-sqlite tests
if: steps.cache-ucm-binaries.outputs.cache-hit != 'true'
run: stack build --fast --test unison-sqlite
- name: unison-syntax tests
if: steps.cache-ucm-binaries.outputs.cache-hit != 'true'
run: stack build --fast --test unison-syntax
- name: unison-util-bytes tests
if: steps.cache-ucm-binaries.outputs.cache-hit != 'true'
run: stack build --fast --test unison-util-bytes
- name: unison-util-cache tests
if: steps.cache-ucm-binaries.outputs.cache-hit != 'true'
run: stack build --fast --test unison-util-cache
- name: unison-util-relation tests
if: steps.cache-ucm-binaries.outputs.cache-hit != 'true'
run: stack build --fast --test unison-util-relation
- name: cli-integration-tests
if: steps.cache-ucm-binaries.outputs.cache-hit != 'true'
run: stack exec cli-integration-tests
- name: verify stack ghci startup
if: runner.os == 'macOS' && steps.cache-ucm-binaries.outputs.cache-hit != 'true'
run: echo | stack ghci
- name: save ucm artifact
uses: actions/upload-artifact@v4
with:
name: unison-${{ matrix.os }}
path: ${{ env.ucm }}
if-no-files-found: error
- name: save stack caches
if: |
!cancelled()
&& steps.restore-stack-caches.outputs.cache-hit != 'true'
&& steps.cache-ucm-binaries.outputs.cache-hit != 'true'
uses: unisonweb/actions/stack/cache/save@main
with:
cache-prefix: ci
transcripts:
name: run transcripts
needs: build-ucm
runs-on: ${{ matrix.os }}
strategy:
# Run each build to completion, regardless of if any have failed
fail-fast: false
matrix:
os:
# While iterating on this file, you can disable one or more of these to speed things up
- ubuntu-20.04
- macos-13
- windows-2019
# - windows-2022
steps:
- uses: actions/checkout@v4
- name: tweak environment
run: |
transcript_test_results="${RUNNER_TEMP//\\//}/${transcript_test_results}"
echo "transcript_test_results=$transcript_test_results" >> $GITHUB_ENV
ucm_local_bin="${RUNNER_TEMP//\\//}/${ucm_local_bin}"
echo "ucm_local_bin=$ucm_local_bin" >> $GITHUB_ENV
if [[ ${{runner.os}} = "Windows" ]]; then
echo "ucm=$ucm_local_bin/unison.exe" >> $GITHUB_ENV
echo "transcripts=$ucm_local_bin/transcripts.exe" >> $GITHUB_ENV
else
echo "ucm=$ucm_local_bin/unison" >> $GITHUB_ENV
echo "transcripts=$ucm_local_bin/transcripts" >> $GITHUB_ENV
fi
- name: cache transcript test results
id: cache-transcript-test-results
uses: actions/cache@v4
with:
path: ${{env.transcript_test_results}}
key: transcripts-results-${{ matrix.os }}-${{ hashFiles('**/stack.yaml', '**/package.yaml', '**/*.hs')}}-${{ hashFiles('**/unison-src/**/*.md', '**/unison-src/**/*.u') }}
- name: restore binaries
uses: actions/cache/restore@v4
if: steps.cache-transcript-test-results.outputs.cache-hit != 'true'
with:
path: ${{env.ucm_local_bin}}
key: ucm-${{ matrix.os }}-${{ hashFiles('**/stack.yaml', '**/package.yaml', '**/*.hs')}}
fail-on-cache-miss: true
# One of the transcripts fails if the user's git name hasn't been set.
## (Which transcript? -AI)
- name: set git user info
run: |
git config --global user.name "GitHub Actions"
git config --global user.email "actions@github.com"
- name: round-trip-tests
if: steps.cache-transcript-test-results.outputs.cache-hit != 'true'
run: |
${{env.ucm}} transcript unison-src/transcripts-round-trip/main.md
${{env.ucm}} transcript unison-src/transcripts-manual/rewrites.md
# Fail if any transcripts cause git diffs.
git diff --ignore-cr-at-eol --exit-code \
unison-src/transcripts-round-trip/main.output.md \
unison-src/transcripts-manual/rewrites.output.md
- name: transcripts
if: steps.cache-transcript-test-results.outputs.cache-hit != 'true'
run: |
${{env.transcripts}}
# Fail if any transcripts cause git diffs.
git diff --ignore-cr-at-eol --exit-code unison-src/transcripts
- name: docs.to-html
if: steps.cache-transcript-test-results.outputs.cache-hit != 'true'
run: |
${{env.ucm}} transcript unison-src/transcripts-manual/docs.to-html.md
# Fail if the output or generated docs differ.
git diff --ignore-cr-at-eol --exit-code \
unison-src/transcripts-manual/docs.to-html.output.md \
unison-src/transcripts-manual/docs.to-html
- name: mark transcripts as passing
if: steps.cache-transcript-test-results.outputs.cache-hit != 'true'
run: |
echo "passing=true" >> "${{env.transcript_test_results}}"
interpreter-tests:
name: run interpreter tests
needs: build-ucm
runs-on: ${{ matrix.os }}
strategy:
# Run each build to completion, regardless of if any have failed
fail-fast: false
matrix:
os:
# While iterating on this file, you can disable one or more of these to speed things up
- ubuntu-20.04
- macos-13
# - windows-2019
# - windows-2022
steps:
- uses: actions/checkout@v4
- name: tweak environment
run: |
interpreter_test_results="${RUNNER_TEMP//\\//}/${interpreter_test_results}"
echo "interpreter_test_results=$interpreter_test_results" >> $GITHUB_ENV
ucm_local_bin="${RUNNER_TEMP//\\//}/${ucm_local_bin}"
echo "ucm_local_bin=$ucm_local_bin" >> $GITHUB_ENV
if [[ ${{runner.os}} = "Windows" ]]; then
echo "ucm=$ucm_local_bin/unison.exe" >> $GITHUB_ENV
echo "transcripts=$ucm_local_bin/transcripts.exe" >> $GITHUB_ENV
else
echo "ucm=$ucm_local_bin/unison" >> $GITHUB_ENV
echo "transcripts=$ucm_local_bin/transcripts" >> $GITHUB_ENV
fi
- name: look up hash for runtime tests
run: echo "runtime_tests_causalhash=$(scripts/get-share-hash.sh ${{env.runtime_tests_version}})" >> $GITHUB_ENV
- name: cache interpreter test results
id: cache-interpreter-test-results
uses: actions/cache@v4
with:
path: ${{env.interpreter_test_results}}
key: interpreter-test-results-${{ matrix.os }}-${{ hashFiles('**/stack.yaml', '**/package.yaml', '**/*.hs')}}-${{ hashFiles('**/interpreter-tests.tpl.md') }}-${{env.runtime_tests_causalhash}}
- name: cache testing codebase
id: cache-testing-codebase
if: steps.cache-interpreter-test-results.outputs.cache-hit != 'true'
uses: actions/cache@v4
with:
path: ${{ env.runtime_tests_codebase }}
key: runtime-tests-codebase-${{env.runtime_tests_causalhash}}
restore-keys: runtime-tests-codebase-
- name: restore binaries
uses: actions/cache/restore@v4
if: steps.cache-interpreter-test-results.outputs.cache-hit != 'true'
with:
path: ${{env.ucm_local_bin}}
key: ucm-${{ matrix.os }}-${{ hashFiles('**/stack.yaml', '**/package.yaml', '**/*.hs')}}
fail-on-cache-miss: true
- name: interpreter tests
# this one should be re-run if the ucm binaries have changed or unison-src/ has changed
if: steps.cache-interpreter-test-results.outputs.cache-hit != 'true'
run: |
envsubst '${runtime_tests_version}' \
< unison-src/builtin-tests/interpreter-tests.tpl.md \
> unison-src/builtin-tests/interpreter-tests.md
${{ env.ucm }} transcript.fork -C ${{ env.runtime_tests_codebase }} unison-src/builtin-tests/interpreter-tests.md
cat unison-src/builtin-tests/interpreter-tests.output.md
git diff --exit-code unison-src/builtin-tests/interpreter-tests.output.md
- name: mark interpreter tests as passing
if: steps.cache-interpreter-test-results.outputs.cache-hit != 'true'
run: |
echo "passing=true" >> "${{env.interpreter_test_results}}"
generate-jit-source:
if: always() && needs.build-ucm.result == 'success'
name: generate jit source
needs: build-ucm
runs-on: ubuntu-20.04
steps:
- name: set up environment
run: |
echo "jit_generated_src_scheme=${{ runner.temp }}/jit-generated-src" >> $GITHUB_ENV
echo "jit_src_scheme=${{ runner.temp }}/${{ env.jit_src_scheme }}" >> $GITHUB_ENV
echo "ucm=${{ runner.temp }}/unison" >> $GITHUB_ENV
- name: download scheme-libs
uses: actions/checkout@v4
with:
sparse-checkout: |
scripts/get-share-hash.sh
scheme-libs
- name: look up hash for jit source generator
run: echo "jit_causalhash=$(scripts/get-share-hash.sh ${{env.jit_version}})" >> $GITHUB_ENV
- uses: actions/cache@v4
name: cache auto-generated jit source
id: cache-generated-source
with:
path: ${{ env.jit_generated_src_scheme }}
key: jit_generated_src_scheme-jit_${{env.jit_version}}-${{env.jit_causalhash}}
- name: create transcript
if: steps.cache-generated-source.outputs.cache-hit != 'true'
uses: DamianReeves/write-file-action@v1.3
with:
path: ${{ runner.temp }}/setup-jit.md
write-mode: overwrite
contents: |
``` ucm
scratch/main> project.create-empty jit-setup
jit-setup/main> lib.install ${{ env.jit_version }}
```
``` unison
go = generateSchemeBoot "${{ env.jit_generated_src_scheme }}"
```
``` ucm
jit-setup/main> run go
```
- name: download ucm artifact
if: steps.cache-generated-source.outputs.cache-hit != 'true'
uses: actions/download-artifact@v4
with:
name: unison-${{ env.jit_generator_os }}
path: ${{ runner.temp }}
- name: set ucm permissions
if: steps.cache-generated-source.outputs.cache-hit != 'true'
run: chmod +x ${{ env.ucm }}
- name: generate source
if: steps.cache-generated-source.outputs.cache-hit != 'true'
run: |
mkdir -p ${{ env.jit_generated_src_scheme }}
${{ env.ucm }} transcript ${{ runner.temp }}/setup-jit.md
- name: bundle source
run: |
mkdir -p ${{ env.jit_src_scheme }}
cp -R scheme-libs/racket/* ${{ env.jit_src_scheme }}
cp -R "${{ env.jit_generated_src_scheme }}"/* ${{ env.jit_src_scheme }}
- name: save jit source
if: always()
uses: actions/upload-artifact@v4
with:
name: jit-source
path: ${{ env.jit_src_scheme }}/**
if-no-files-found: error
build-jit-binary:
name: build jit binary
needs: generate-jit-source
uses: ./.github/workflows/ci-build-jit-binary.yaml
test-jit:
name: test jit
needs: build-jit-binary
uses: ./.github/workflows/ci-test-jit.yaml