Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/fixtures/Main.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module Main where

import Prelude

import Effect (Effect)
import Effect.Console (log)

main :: Effect Unit
main = log "setup-purescript smoke"
6 changes: 6 additions & 0 deletions .github/fixtures/legacy/spago.dhall
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{ name = "setup-purescript-smoke"
, dependencies = [ "console", "effect", "prelude" ]
, packages =
https://github.com/purescript/package-sets/releases/download/psc-0.15.15-20261009/packages.dhall
, sources = [ "src/**/*.purs" ]
}
9 changes: 9 additions & 0 deletions .github/fixtures/modern/spago.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package:
name: setup-purescript-smoke
dependencies:
- console
- effect
- prelude
workspace:
packageSet:
registry: 50.4.0
150 changes: 126 additions & 24 deletions .github/workflows/integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,39 +7,141 @@ on:
schedule:
- cron: "0 5 * * *"

permissions:
contents: read

jobs:
build:
runs-on: ubuntu-latest
env:
USE_LOCAL_VERSIONS_JSON: 1
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: actions/setup-node@v7
with:
node-version: "24"
package-manager-cache: false
- uses: ./
with:
purescript: "0.15.15"
spago: "1.0.4"
psa: ""
purs-tidy: "0.11.1"
- run: npm ci
- run: npm run check
- run: npm run build
- name: Check committed bundles and lockfile are reproducible
run: |
npm run bundle
git -c core.fileMode=false diff --exit-code -- dist spago.yaml spago.lock
sha256sum dist/index.js dist/update.js > "$RUNNER_TEMP/bundles.sha256"
npm run bundle
sha256sum -c "$RUNNER_TEMP/bundles.sha256"

test-install:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
# The existing compiler and legacy Spago tarballs target x86-64.
os: [ubuntu-latest, macos-15-intel, windows-latest]
toolchain: [defaults, latest, pinned, legacy]
include:
- toolchain: latest
spago: "latest"
psa: "latest"
- toolchain: pinned
spago: "1.0.4"
psa: ""
- toolchain: legacy
spago: "0.21.0"
psa: "0.8.2"
env:
USE_LOCAL_VERSIONS_JSON: 1

defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v4

# We set LF endings so that the Windows environment is consistent with the rest
# See here for context: https://github.com/actions/checkout/issues/135
- name: Set git to use LF
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: actions/setup-node@v7
with:
node-version: "24"
package-manager-cache: false
- name: Confirm tools are absent before installation
run: |
git config --global core.autocrlf false
git config --global core.eol lf
git config --global core.longpaths true

- uses: ./ # equivalent to purescript-contrib/setup-purescript@<branch>
if command -v spago || command -v psa; then
echo 'Toolchain is already installed; this would hide installation failures.'
exit 1
fi
- name: Install default toolchain
if: matrix.toolchain == 'defaults'
uses: ./
- name: Install explicit toolchain
if: matrix.toolchain != 'defaults'
uses: ./
with:
purs-tidy: "latest"
zephyr: "latest"
spago: "unstable"

- name: Check spago and purs are installed correctly
purescript: "0.15.15"
spago: ${{ matrix.spago }}
psa: ${{ matrix.psa }}
- name: Assert installed versions and PSA opt-out
env:
TOOLCHAIN: ${{ matrix.toolchain }}
run: |
purs --version
spago --version

- name: Check purescript code is formatted
# because errors with 'Some files are not formatted', dont know why
if: runner.os != 'Windows'
test "$(node -p 'process.versions.node.split(".")[0]')" = 24
expected_purs=0.15.15
expected_spago=1.0.4
expected_psa=0.9.0
if [ "$TOOLCHAIN" = defaults ]; then
expected_purs=$(node -p 'JSON.parse(require("fs").readFileSync("dist/versions-v2.json")).purs.latest')
fi
if [ "$TOOLCHAIN" = defaults ] || [ "$TOOLCHAIN" = latest ]; then
expected_spago=$(node -p 'JSON.parse(require("fs").readFileSync("dist/versions-v2.json")).spago.latest')
expected_psa=$(node -p 'JSON.parse(require("fs").readFileSync("dist/versions-v2.json")).psa.latest')
fi
if [ "$TOOLCHAIN" = legacy ]; then
expected_spago=0.21.0
expected_psa=0.8.2
fi
test "$(purs --version)" = "$expected_purs"
test "$(spago --version)" = "$expected_spago"
if [ "$TOOLCHAIN" = pinned ]; then
if command -v psa; then
echo 'PSA was installed despite the empty input.'
exit 1
fi
else
actual_psa=$(psa --version)
test "${actual_psa#v}" = "$expected_psa"
fi
echo "EXPECTED_SPAGO=$expected_spago" >> "$GITHUB_ENV"
echo "EXPECTED_PSA=$expected_psa" >> "$GITHUB_ENV"
- name: Assert Windows npm command shims
if: runner.os == 'Windows' && matrix.toolchain != 'legacy'
shell: pwsh
env:
TOOLCHAIN: ${{ matrix.toolchain }}
run: |
if ((spago.cmd --version) -ne $env:EXPECTED_SPAGO) { throw 'Incorrect spago.cmd version' }
if ($env:TOOLCHAIN -ne 'pinned') {
if ((psa.cmd --version).TrimStart('v') -ne $env:EXPECTED_PSA) { throw 'Incorrect psa.cmd version' }
}
- name: Build and run a consumer project
env:
TOOLCHAIN: ${{ matrix.toolchain }}
run: |
npm run check
smoke="$RUNNER_TEMP/setup-purescript-smoke"
mkdir -p "$smoke/src"
cp .github/fixtures/Main.purs "$smoke/src/Main.purs"
if [ "$TOOLCHAIN" = legacy ]; then
cp .github/fixtures/legacy/spago.dhall "$smoke/spago.dhall"
else
cp .github/fixtures/modern/spago.yaml "$smoke/spago.yaml"
fi
cd "$smoke"
spago build
spago run | tee result.txt
grep -Fx 'setup-purescript smoke' result.txt
7 changes: 4 additions & 3 deletions .github/workflows/sync.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,17 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
with:
# Otherwise the token used is the GITHUB_TOKEN instead of personal
persist-credentials: false
# Otherwise will fail to push refs to destination repo
fetch-depth: 0

- uses: actions/setup-node@v1
- uses: actions/setup-node@v7
with:
node-version: "18"
node-version: "24"
package-manager-cache: false

- name: Update tooling versions
run: |
Expand Down
75 changes: 42 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,17 @@ A GitHub Action which sets up a PureScript toolchain for CI. Contains the follow

- The [PureScript compiler](https://github.com/purescript/purescript)
- The [Spago package manager and build tool](https://github.com/purescript/spago)
- Use the `unstable` version for spago-next; otherwise, setup-purescript provides [`spago-legacy`](https://github.com/purescript/spago-legacy); see [issue 37](https://github.com/purescript-contrib/setup-purescript/issues/37)
- `latest` currently selects Spago 1.x. Pin an exact legacy version, such as `0.21.0`, for projects using Dhall configuration.
- The [`psa` error reporting frontend for the compiler](https://github.com/natefaubion/purescript-psa)

You can also optionally include the following tools:

- The [`purs-tidy` code formatter](https://github.com/natefaubion/purescript-tidy)
- The [Zephyr dead code elimination tool](https://github.com/coot/zephyr)

This action is designed to support PureScript tools. Your PureScript project may also depend on tooling and libraries provided by the NPM ecosystem, in which case you will also want to use the [setup-node](https://github.com/actions/setup-node) action.
The action itself runs on GitHub's Node24 action runtime. This does **not** select the Node executable on your workflow's `PATH`: installed npm tools use that separate Node installation. Spago 1.0.4 requires Node >=22.5.0. Use [setup-node](https://github.com/actions/setup-node) with Node24 **before** this action, as shown below.

Self-hosted runners need Actions Runner v2.327.1 or newer for the Node24 action runtime. Node24 does not support macOS 13.4 or earlier, or officially support ARM32. The compiler and legacy-tool downloads still use the existing x86-64 tarballs; this runtime update does not add native ARM64 tool installation. Integration tests cover Linux, Intel macOS, and Windows.

## Usage

Expand All @@ -27,35 +29,45 @@ Use the PureScript toolchain with the latest versions of PureScript and Spago:

```yaml
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: "24"
- uses: purescript-contrib/setup-purescript@main
- run: spago build
```

Other tools are not enabled by default, but you can enable them by specifying their version.
This installs PureScript, Spago, and PSA. Only purs-tidy and Zephyr are opt-in.

### Specify Versions

Each tool can accept one of the following:
- a semantic version (only exact versions currently supported)
- the string `"latest"`, which represents the latest version that uses major, minor, and patch, but will omit versions using pre-release identifiers or build metadata
- the string `"unstable"`, which represents the latest version no matter what it is (i.e. pre-release identifiers and build metadata are not considered).
- `"latest"`, which selects the tool's recorded stable version
- `"unstable"`, which selects the tool's recorded unstable version
- `""`, which skips installation of that tool, including tools enabled by default.

Aliases are resolved from [`dist/versions-v2.json`](dist/versions-v2.json) on `main`, even when you pin an action release. For Spago and purs-tidy, the version updater reads npm's `latest` and `next` dist-tags, falling back to `latest` when `next` is absent. `unstable` does not necessarily mean a newer version: Spago's recorded unstable version is currently 0.93.x, while its latest version is 1.x. Use exact tool versions for reproducible selection.

Tools that are not installed by default must be specified this way to be included in the toolchain.

```yaml
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: "24"
- uses: purescript-contrib/setup-purescript@main
with:
purescript: "0.14.0"
psa: "0.8.2"
spago: "latest"
purescript: "0.15.15"
psa: ""
spago: "1.0.4"
purs-tidy: "latest"
zephyr: "0.3.2"
- run: spago build
```

Omitting `psa` still installs it; only the explicit empty string above disables it. Legacy Spago and PSA pins remain supported, for example `spago: "0.21.0"` and `psa: "0.8.2"`. Bower/Pulp consumers can set `spago: ""` if they do not need Spago, and should install Bower/Pulp separately.

## Full Example Workflow

This workflow is a useful starting point for new projects and libraries. You can add a `.yml` file with the contents below to the `.github/workflows` directory in your project (for example: `.github/workflows/ci.yml`).
Expand All @@ -69,52 +81,49 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v7

- uses: actions/setup-node@v7
with:
node-version: "24"

- uses: purescript-contrib/setup-purescript@main

- name: Cache PureScript dependencies
uses: actions/cache@v2
# This cache uses the .dhall files to know when it should reinstall
# and rebuild packages. It caches both the installed packages from
# the `.spago` directory and compilation artifacts from the `output`
# directory. When restored the compiler will rebuild any files that
# have changed. If you do not want to cache compiled output, remove
# the `output` path.
uses: actions/cache@v6
# For registry-based Spago projects. Legacy projects should hash
# their *.dhall files instead.
with:
key: ${{ runner.os }}-spago-${{ hashFiles('**/*.dhall') }}
key: ${{ runner.os }}-spago-${{ hashFiles('**/spago.yaml', '**/spago.lock') }}
path: |
.spago
output

- run: spago build

- run: spago test --no-install
- run: spago test
```

## Development

Enter a development shell with necessary tools installed:
Use Node24 and the pinned build tools used by Integration:

```sh
nix-shell
npm install --global purescript@0.15.15 spago@1.0.4 purs-tidy@0.11.1
npm ci
npm run check
npm run build
```

If you need any additional tools not included in this Nix expression or available via NPM, please feel free to add them via [easy-purescript-nix](https://github.com/justinwoo/easy-purescript-nix).

Next, install NPM dependencies:
`npm run build` compiles and checks dependencies; it does not regenerate the action. After source changes, regenerate the checked-in bundles:

```sh
npm install
npm run bundle
```

GitHub Actions uses the `action.yml` file to define the action and the `dist/index.js` file to execute it. After making any changes to the source code, make sure those changes are visible by running:

```sh
npm run build
```
The small `index.js` and `update.js` entry points import freshly compiled code from `output/index.js`. Bundling produces `dist/index.js` (the action) and `dist/update.js` (the version updater). Commit generated bundle changes together with their source. Integration checks that rebuilding produces the committed contents and that two consecutive builds are identical.

This will bundle and minify the source code so it is available to the end user.
Integration also installs default, latest, pinned modern, and pinned legacy toolchains on all three operating systems, checks PSA opt-out and Windows npm shims, and builds/runs small registry and Dhall consumer fixtures. It has read-only repository permissions and never runs the version updater. **Sync Versions is separate:** it writes both shared version manifests and commits/pushes them. Do not run or enable it merely to validate a code change.

## Used By

Expand Down
2 changes: 1 addition & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ inputs:
zephyr:
description: "The Zephyr version to install. Examples: latest, 0.3.2"
runs:
using: "node20"
using: "node24"
main: "dist/index.js"
branding:
icon: "download"
Expand Down
5 changes: 2 additions & 3 deletions dist/index.js

Large diffs are not rendered by default.

Loading
Loading