├── .github └── workflows │ ├── integration.yml │ └── sync.yml ├── .gitignore ├── LICENSE ├── README.md ├── action.yml ├── dist ├── index.js ├── package.json ├── update.js ├── versions-v2.json └── versions.json ├── flake.lock ├── flake.nix ├── index.js ├── package-lock.json ├── package.json ├── spago.lock ├── spago.yaml ├── src ├── Main.purs └── Setup │ ├── BuildPlan.purs │ ├── Data │ ├── Key.purs │ ├── Platform.purs │ ├── Tool.purs │ └── VersionFiles.purs │ ├── GetTool.purs │ └── UpdateVersions.purs └── update.js /.github/workflows/integration.yml: -------------------------------------------------------------------------------- 1 | name: Integration 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | schedule: 8 | - cron: "0 5 * * *" 9 | 10 | jobs: 11 | test-install: 12 | runs-on: ${{ matrix.os }} 13 | strategy: 14 | matrix: 15 | os: [ubuntu-latest, macos-latest, windows-latest] 16 | env: 17 | USE_LOCAL_VERSIONS_JSON: 1 18 | 19 | steps: 20 | - uses: actions/checkout@v4 21 | 22 | # We set LF endings so that the Windows environment is consistent with the rest 23 | # See here for context: https://github.com/actions/checkout/issues/135 24 | - name: Set git to use LF 25 | run: | 26 | git config --global core.autocrlf false 27 | git config --global core.eol lf 28 | git config --global core.longpaths true 29 | 30 | - uses: ./ # equivalent to purescript-contrib/setup-purescript@ 31 | with: 32 | purs-tidy: "latest" 33 | zephyr: "latest" 34 | spago: "unstable" 35 | 36 | - name: Check spago and purs are installed correctly 37 | run: | 38 | purs --version 39 | spago --version 40 | 41 | - name: Check purescript code is formatted 42 | # because errors with 'Some files are not formatted', dont know why 43 | if: runner.os != 'Windows' 44 | run: | 45 | npm run check 46 | -------------------------------------------------------------------------------- /.github/workflows/sync.yml: -------------------------------------------------------------------------------- 1 | name: Sync Versions 2 | 3 | on: 4 | schedule: 5 | - cron: "0 4 * * *" 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v4 12 | with: 13 | # Otherwise the token used is the GITHUB_TOKEN instead of personal 14 | persist-credentials: false 15 | # Otherwise will fail to push refs to destination repo 16 | fetch-depth: 0 17 | 18 | - uses: actions/setup-node@v1 19 | with: 20 | node-version: "18" 21 | 22 | - name: Update tooling versions 23 | run: | 24 | git config --local pull.ff only 25 | git config --local user.email "action@github.com" 26 | git config --local user.name "GitHub Action" 27 | 28 | git pull 29 | node ./dist/update.js 30 | git diff --quiet || git commit -a -m "Sync repository with latest tooling." 31 | 32 | - name: Push changes 33 | uses: ad-m/github-push-action@master 34 | with: 35 | branch: ${{ github.ref }} 36 | github_token: ${{ secrets.GITHUB_TOKEN }} 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore dotfiles except for explicit exceptions 2 | /.* 3 | !/.gitignore 4 | !/.github 5 | 6 | # Dependencies 7 | node_modules 8 | 9 | # PureScript 10 | output 11 | dce-output 12 | generated-docs 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Thomas Honeyman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Setup PureScript Action 2 | 3 | [![Integration](https://github.com/thomashoneyman/setup-purescript/workflows/Integration/badge.svg?branch=main)](https://github.com/thomashoneyman/setup-purescript/actions?query=workflow%3AIntegration+branch%3Amain) 4 | [![Sync Versions](https://github.com/thomashoneyman/setup-purescript/workflows/Sync%20Versions/badge.svg?branch=main)](https://github.com/thomashoneyman/setup-purescript/actions?query=workflow%3A"Sync+Versions"+branch%3Amain) 5 | 6 | A GitHub Action which sets up a PureScript toolchain for CI. Contains the following tools by default: 7 | 8 | - The [PureScript compiler](https://github.com/purescript/purescript) 9 | - The [Spago package manager and build tool](https://github.com/purescript/spago) 10 | - 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) 11 | - The [`psa` error reporting frontend for the compiler](https://github.com/natefaubion/purescript-psa) 12 | 13 | You can also optionally include the following tools: 14 | 15 | - The [`purs-tidy` code formatter](https://github.com/natefaubion/purescript-tidy) 16 | - The [Zephyr dead code elimination tool](https://github.com/coot/zephyr) 17 | 18 | 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. 19 | 20 | ## Usage 21 | 22 | See the [action.yml](action.yml) file for all possible inputs and outputs. 23 | 24 | ### Basic 25 | 26 | Use the PureScript toolchain with the latest versions of PureScript and Spago: 27 | 28 | ```yaml 29 | steps: 30 | - uses: actions/checkout@v2 31 | - uses: purescript-contrib/setup-purescript@main 32 | - run: spago build 33 | ``` 34 | 35 | Other tools are not enabled by default, but you can enable them by specifying their version. 36 | 37 | ### Specify Versions 38 | 39 | Each tool can accept one of the following: 40 | - a semantic version (only exact versions currently supported) 41 | - 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 42 | - the string `"unstable"`, which represents the latest version no matter what it is (i.e. pre-release identifiers and build metadata are not considered). 43 | 44 | Tools that are not installed by default must be specified this way to be included in the toolchain. 45 | 46 | ```yaml 47 | steps: 48 | - uses: actions/checkout@v2 49 | - uses: purescript-contrib/setup-purescript@main 50 | with: 51 | purescript: "0.14.0" 52 | psa: "0.8.2" 53 | spago: "latest" 54 | purs-tidy: "latest" 55 | zephyr: "0.3.2" 56 | - run: spago build 57 | ``` 58 | 59 | ## Full Example Workflow 60 | 61 | 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`). 62 | 63 | ```yml 64 | name: CI 65 | 66 | on: push 67 | 68 | jobs: 69 | build: 70 | runs-on: ubuntu-latest 71 | steps: 72 | - uses: actions/checkout@v2 73 | 74 | - uses: purescript-contrib/setup-purescript@main 75 | 76 | - name: Cache PureScript dependencies 77 | uses: actions/cache@v2 78 | # This cache uses the .dhall files to know when it should reinstall 79 | # and rebuild packages. It caches both the installed packages from 80 | # the `.spago` directory and compilation artifacts from the `output` 81 | # directory. When restored the compiler will rebuild any files that 82 | # have changed. If you do not want to cache compiled output, remove 83 | # the `output` path. 84 | with: 85 | key: ${{ runner.os }}-spago-${{ hashFiles('**/*.dhall') }} 86 | path: | 87 | .spago 88 | output 89 | 90 | - run: spago build 91 | 92 | - run: spago test --no-install 93 | ``` 94 | 95 | ## Development 96 | 97 | Enter a development shell with necessary tools installed: 98 | 99 | ```sh 100 | nix-shell 101 | ``` 102 | 103 | 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). 104 | 105 | Next, install NPM dependencies: 106 | 107 | ```sh 108 | npm install 109 | ``` 110 | 111 | 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: 112 | 113 | ```sh 114 | npm run build 115 | ``` 116 | 117 | This will bundle and minify the source code so it is available to the end user. 118 | 119 | ## Used By 120 | 121 | These libraries and applications are examples of `setup-purescript` in action: 122 | 123 | - [halogen](https://github.com/purescript-halogen/purescript-halogen/blob/master/.github/workflows/ci.yml) 124 | - [halogen-realworld](https://github.com/thomashoneyman/purescript-halogen-realworld/blob/main/.github/workflows/ci.yml) 125 | - [halogen-formless](https://github.com/thomashoneyman/purescript-halogen-formless/blob/main/.github/workflows/ci.yml) 126 | - [halogen-hooks](https://github.com/thomashoneyman/purescript-halogen-hooks/blob/main/.github/workflows/ci.yml) 127 | - [slug](https://github.com/thomashoneyman/purescript-slug/blob/main/.github/workflows/ci.yml) 128 | - ...add your package here! 129 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: "Set up a PureScript toolchain" 2 | description: "Install a PureScript toolchain and add it to the PATH" 3 | author: "Thomas Honeyman " 4 | inputs: 5 | purescript: 6 | description: "The compiler version to install. Examples: latest, 0.13.8" 7 | default: "latest" 8 | spago: 9 | description: "The Spago version to install. Examples: latest, 0.15.3" 10 | default: "latest" 11 | psa: 12 | description: "The psa version to install. Examples: latest, 0.7.2" 13 | default: "latest" 14 | purs-tidy: 15 | description: "The purs-tidy version to install. Examples: latest, 0.1.1" 16 | zephyr: 17 | description: "The Zephyr version to install. Examples: latest, 0.3.2" 18 | runs: 19 | using: "node20" 20 | main: "dist/index.js" 21 | branding: 22 | icon: "download" 23 | color: "gray-dark" 24 | -------------------------------------------------------------------------------- /dist/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module" 3 | } 4 | -------------------------------------------------------------------------------- /dist/versions-v2.json: -------------------------------------------------------------------------------- 1 | { 2 | "purs": { 3 | "unstable": "0.15.16-5", 4 | "latest": "0.15.15" 5 | }, 6 | "spago": { 7 | "unstable": "0.93.44", 8 | "latest": "0.21.0" 9 | }, 10 | "psa": { 11 | "unstable": "0.9.0", 12 | "latest": "0.9.0" 13 | }, 14 | "purs-tidy": { 15 | "unstable": "0.11.1", 16 | "latest": "0.11.1" 17 | }, 18 | "zephyr": { 19 | "unstable": "0.5.2", 20 | "latest": "0.5.2" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /dist/versions.json: -------------------------------------------------------------------------------- 1 | { 2 | "purs": "0.15.15", 3 | "spago": "0.21.0", 4 | "psa": "0.9.0", 5 | "purs-tidy": "0.11.1", 6 | "zephyr": "0.5.2" 7 | } 8 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "flake-compat": { 4 | "flake": false, 5 | "locked": { 6 | "lastModified": 1696426674, 7 | "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", 8 | "owner": "edolstra", 9 | "repo": "flake-compat", 10 | "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", 11 | "type": "github" 12 | }, 13 | "original": { 14 | "owner": "edolstra", 15 | "repo": "flake-compat", 16 | "type": "github" 17 | } 18 | }, 19 | "nixpkgs": { 20 | "locked": { 21 | "lastModified": 1712168706, 22 | "narHash": "sha256-XP24tOobf6GGElMd0ux90FEBalUtw6NkBSVh/RlA6ik=", 23 | "owner": "NixOS", 24 | "repo": "nixpkgs", 25 | "rev": "1487bdea619e4a7a53a4590c475deabb5a9d1bfb", 26 | "type": "github" 27 | }, 28 | "original": { 29 | "owner": "NixOS", 30 | "ref": "nixos-23.11", 31 | "repo": "nixpkgs", 32 | "type": "github" 33 | } 34 | }, 35 | "purescript-overlay": { 36 | "inputs": { 37 | "flake-compat": "flake-compat", 38 | "nixpkgs": [ 39 | "nixpkgs" 40 | ], 41 | "slimlock": "slimlock" 42 | }, 43 | "locked": { 44 | "lastModified": 1712144948, 45 | "narHash": "sha256-hPnJ8BUr7FeoaX21Mr+asfJU5d6+E228Rn+YS2GPZ5w=", 46 | "owner": "thomashoneyman", 47 | "repo": "purescript-overlay", 48 | "rev": "5cc5505bc99898eb13aa075841810aeb7181e98c", 49 | "type": "github" 50 | }, 51 | "original": { 52 | "owner": "thomashoneyman", 53 | "repo": "purescript-overlay", 54 | "type": "github" 55 | } 56 | }, 57 | "root": { 58 | "inputs": { 59 | "nixpkgs": "nixpkgs", 60 | "purescript-overlay": "purescript-overlay" 61 | } 62 | }, 63 | "slimlock": { 64 | "inputs": { 65 | "nixpkgs": [ 66 | "purescript-overlay", 67 | "nixpkgs" 68 | ] 69 | }, 70 | "locked": { 71 | "lastModified": 1688756706, 72 | "narHash": "sha256-xzkkMv3neJJJ89zo3o2ojp7nFeaZc2G0fYwNXNJRFlo=", 73 | "owner": "thomashoneyman", 74 | "repo": "slimlock", 75 | "rev": "cf72723f59e2340d24881fd7bf61cb113b4c407c", 76 | "type": "github" 77 | }, 78 | "original": { 79 | "owner": "thomashoneyman", 80 | "repo": "slimlock", 81 | "type": "github" 82 | } 83 | } 84 | }, 85 | "root": "root", 86 | "version": 7 87 | } 88 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs = { 3 | nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11"; 4 | purescript-overlay = { 5 | url = "github:thomashoneyman/purescript-overlay"; 6 | inputs.nixpkgs.follows = "nixpkgs"; 7 | }; 8 | }; 9 | 10 | outputs = { self, nixpkgs, ... }@inputs: 11 | let 12 | supportedSystems = ["x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin"]; 13 | 14 | forAllSystems = nixpkgs.lib.genAttrs supportedSystems; 15 | 16 | nixpkgsFor = forAllSystems (system: import nixpkgs { 17 | inherit system; 18 | config = { }; 19 | overlays = builtins.attrValues self.overlays; 20 | }); 21 | in { 22 | overlays = { 23 | purescript = inputs.purescript-overlay.overlays.default; 24 | }; 25 | 26 | # fix 27 | # does not provide attribute 'packages.x86_64-linux.default' or 'defaultPackage.x86_64-linux' 28 | # on `nix shell` 29 | packages = self.devShells; 30 | 31 | devShells = forAllSystems (system: 32 | # pkgs now has access to the standard PureScript toolchain 33 | let pkgs = nixpkgsFor.${system}; in { 34 | default = pkgs.mkShell { 35 | name = "setup-purescript"; 36 | buildInputs = with pkgs; [ 37 | purs 38 | spago-unstable 39 | nodejs_latest 40 | ]; 41 | 42 | shellHook = '' 43 | source <(node --completion-bash) 44 | source <(spago --bash-completion-script `which spago`) 45 | ''; 46 | }; 47 | }); 48 | }; 49 | } 50 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "setup-purescript", 3 | "lockfileVersion": 3, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "name": "setup-purescript", 8 | "license": "MIT", 9 | "dependencies": { 10 | "@actions/core": "^1.10.1", 11 | "@actions/exec": "^1.1.1", 12 | "@actions/tool-cache": "^2.0.1", 13 | "xhr2": "^0.2.1" 14 | }, 15 | "devDependencies": { 16 | "@vercel/ncc": "^0.38.1", 17 | "esbuild": "0.20.1" 18 | } 19 | }, 20 | "node_modules/@actions/core": { 21 | "version": "1.10.1", 22 | "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.1.tgz", 23 | "integrity": "sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==", 24 | "dependencies": { 25 | "@actions/http-client": "^2.0.1", 26 | "uuid": "^8.3.2" 27 | } 28 | }, 29 | "node_modules/@actions/core/node_modules/uuid": { 30 | "version": "8.3.2", 31 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", 32 | "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", 33 | "bin": { 34 | "uuid": "dist/bin/uuid" 35 | } 36 | }, 37 | "node_modules/@actions/exec": { 38 | "version": "1.1.1", 39 | "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz", 40 | "integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==", 41 | "dependencies": { 42 | "@actions/io": "^1.0.1" 43 | } 44 | }, 45 | "node_modules/@actions/http-client": { 46 | "version": "2.2.1", 47 | "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.1.tgz", 48 | "integrity": "sha512-KhC/cZsq7f8I4LfZSJKgCvEwfkE8o1538VoBeoGzokVLLnbFDEAdFD3UhoMklxo2un9NJVBdANOresx7vTHlHw==", 49 | "dependencies": { 50 | "tunnel": "^0.0.6", 51 | "undici": "^5.25.4" 52 | } 53 | }, 54 | "node_modules/@actions/io": { 55 | "version": "1.1.3", 56 | "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz", 57 | "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==" 58 | }, 59 | "node_modules/@actions/tool-cache": { 60 | "version": "2.0.1", 61 | "resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-2.0.1.tgz", 62 | "integrity": "sha512-iPU+mNwrbA8jodY8eyo/0S/QqCKDajiR8OxWTnSk/SnYg0sj8Hp4QcUEVC1YFpHWXtrfbQrE13Jz4k4HXJQKcA==", 63 | "dependencies": { 64 | "@actions/core": "^1.2.6", 65 | "@actions/exec": "^1.0.0", 66 | "@actions/http-client": "^2.0.1", 67 | "@actions/io": "^1.1.1", 68 | "semver": "^6.1.0", 69 | "uuid": "^3.3.2" 70 | } 71 | }, 72 | "node_modules/@esbuild/aix-ppc64": { 73 | "version": "0.20.1", 74 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.1.tgz", 75 | "integrity": "sha512-m55cpeupQ2DbuRGQMMZDzbv9J9PgVelPjlcmM5kxHnrBdBx6REaEd7LamYV7Dm8N7rCyR/XwU6rVP8ploKtIkA==", 76 | "cpu": [ 77 | "ppc64" 78 | ], 79 | "dev": true, 80 | "optional": true, 81 | "os": [ 82 | "aix" 83 | ], 84 | "engines": { 85 | "node": ">=12" 86 | } 87 | }, 88 | "node_modules/@esbuild/android-arm": { 89 | "version": "0.20.1", 90 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.1.tgz", 91 | "integrity": "sha512-4j0+G27/2ZXGWR5okcJi7pQYhmkVgb4D7UKwxcqrjhvp5TKWx3cUjgB1CGj1mfdmJBQ9VnUGgUhign+FPF2Zgw==", 92 | "cpu": [ 93 | "arm" 94 | ], 95 | "dev": true, 96 | "optional": true, 97 | "os": [ 98 | "android" 99 | ], 100 | "engines": { 101 | "node": ">=12" 102 | } 103 | }, 104 | "node_modules/@esbuild/android-arm64": { 105 | "version": "0.20.1", 106 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.1.tgz", 107 | "integrity": "sha512-hCnXNF0HM6AjowP+Zou0ZJMWWa1VkD77BXe959zERgGJBBxB+sV+J9f/rcjeg2c5bsukD/n17RKWXGFCO5dD5A==", 108 | "cpu": [ 109 | "arm64" 110 | ], 111 | "dev": true, 112 | "optional": true, 113 | "os": [ 114 | "android" 115 | ], 116 | "engines": { 117 | "node": ">=12" 118 | } 119 | }, 120 | "node_modules/@esbuild/android-x64": { 121 | "version": "0.20.1", 122 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.1.tgz", 123 | "integrity": "sha512-MSfZMBoAsnhpS+2yMFYIQUPs8Z19ajwfuaSZx+tSl09xrHZCjbeXXMsUF/0oq7ojxYEpsSo4c0SfjxOYXRbpaA==", 124 | "cpu": [ 125 | "x64" 126 | ], 127 | "dev": true, 128 | "optional": true, 129 | "os": [ 130 | "android" 131 | ], 132 | "engines": { 133 | "node": ">=12" 134 | } 135 | }, 136 | "node_modules/@esbuild/darwin-arm64": { 137 | "version": "0.20.1", 138 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.1.tgz", 139 | "integrity": "sha512-Ylk6rzgMD8klUklGPzS414UQLa5NPXZD5tf8JmQU8GQrj6BrFA/Ic9tb2zRe1kOZyCbGl+e8VMbDRazCEBqPvA==", 140 | "cpu": [ 141 | "arm64" 142 | ], 143 | "dev": true, 144 | "optional": true, 145 | "os": [ 146 | "darwin" 147 | ], 148 | "engines": { 149 | "node": ">=12" 150 | } 151 | }, 152 | "node_modules/@esbuild/darwin-x64": { 153 | "version": "0.20.1", 154 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.1.tgz", 155 | "integrity": "sha512-pFIfj7U2w5sMp52wTY1XVOdoxw+GDwy9FsK3OFz4BpMAjvZVs0dT1VXs8aQm22nhwoIWUmIRaE+4xow8xfIDZA==", 156 | "cpu": [ 157 | "x64" 158 | ], 159 | "dev": true, 160 | "optional": true, 161 | "os": [ 162 | "darwin" 163 | ], 164 | "engines": { 165 | "node": ">=12" 166 | } 167 | }, 168 | "node_modules/@esbuild/freebsd-arm64": { 169 | "version": "0.20.1", 170 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.1.tgz", 171 | "integrity": "sha512-UyW1WZvHDuM4xDz0jWun4qtQFauNdXjXOtIy7SYdf7pbxSWWVlqhnR/T2TpX6LX5NI62spt0a3ldIIEkPM6RHw==", 172 | "cpu": [ 173 | "arm64" 174 | ], 175 | "dev": true, 176 | "optional": true, 177 | "os": [ 178 | "freebsd" 179 | ], 180 | "engines": { 181 | "node": ">=12" 182 | } 183 | }, 184 | "node_modules/@esbuild/freebsd-x64": { 185 | "version": "0.20.1", 186 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.1.tgz", 187 | "integrity": "sha512-itPwCw5C+Jh/c624vcDd9kRCCZVpzpQn8dtwoYIt2TJF3S9xJLiRohnnNrKwREvcZYx0n8sCSbvGH349XkcQeg==", 188 | "cpu": [ 189 | "x64" 190 | ], 191 | "dev": true, 192 | "optional": true, 193 | "os": [ 194 | "freebsd" 195 | ], 196 | "engines": { 197 | "node": ">=12" 198 | } 199 | }, 200 | "node_modules/@esbuild/linux-arm": { 201 | "version": "0.20.1", 202 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.1.tgz", 203 | "integrity": "sha512-LojC28v3+IhIbfQ+Vu4Ut5n3wKcgTu6POKIHN9Wpt0HnfgUGlBuyDDQR4jWZUZFyYLiz4RBBBmfU6sNfn6RhLw==", 204 | "cpu": [ 205 | "arm" 206 | ], 207 | "dev": true, 208 | "optional": true, 209 | "os": [ 210 | "linux" 211 | ], 212 | "engines": { 213 | "node": ">=12" 214 | } 215 | }, 216 | "node_modules/@esbuild/linux-arm64": { 217 | "version": "0.20.1", 218 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.1.tgz", 219 | "integrity": "sha512-cX8WdlF6Cnvw/DO9/X7XLH2J6CkBnz7Twjpk56cshk9sjYVcuh4sXQBy5bmTwzBjNVZze2yaV1vtcJS04LbN8w==", 220 | "cpu": [ 221 | "arm64" 222 | ], 223 | "dev": true, 224 | "optional": true, 225 | "os": [ 226 | "linux" 227 | ], 228 | "engines": { 229 | "node": ">=12" 230 | } 231 | }, 232 | "node_modules/@esbuild/linux-ia32": { 233 | "version": "0.20.1", 234 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.1.tgz", 235 | "integrity": "sha512-4H/sQCy1mnnGkUt/xszaLlYJVTz3W9ep52xEefGtd6yXDQbz/5fZE5dFLUgsPdbUOQANcVUa5iO6g3nyy5BJiw==", 236 | "cpu": [ 237 | "ia32" 238 | ], 239 | "dev": true, 240 | "optional": true, 241 | "os": [ 242 | "linux" 243 | ], 244 | "engines": { 245 | "node": ">=12" 246 | } 247 | }, 248 | "node_modules/@esbuild/linux-loong64": { 249 | "version": "0.20.1", 250 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.1.tgz", 251 | "integrity": "sha512-c0jgtB+sRHCciVXlyjDcWb2FUuzlGVRwGXgI+3WqKOIuoo8AmZAddzeOHeYLtD+dmtHw3B4Xo9wAUdjlfW5yYA==", 252 | "cpu": [ 253 | "loong64" 254 | ], 255 | "dev": true, 256 | "optional": true, 257 | "os": [ 258 | "linux" 259 | ], 260 | "engines": { 261 | "node": ">=12" 262 | } 263 | }, 264 | "node_modules/@esbuild/linux-mips64el": { 265 | "version": "0.20.1", 266 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.1.tgz", 267 | "integrity": "sha512-TgFyCfIxSujyuqdZKDZ3yTwWiGv+KnlOeXXitCQ+trDODJ+ZtGOzLkSWngynP0HZnTsDyBbPy7GWVXWaEl6lhA==", 268 | "cpu": [ 269 | "mips64el" 270 | ], 271 | "dev": true, 272 | "optional": true, 273 | "os": [ 274 | "linux" 275 | ], 276 | "engines": { 277 | "node": ">=12" 278 | } 279 | }, 280 | "node_modules/@esbuild/linux-ppc64": { 281 | "version": "0.20.1", 282 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.1.tgz", 283 | "integrity": "sha512-b+yuD1IUeL+Y93PmFZDZFIElwbmFfIKLKlYI8M6tRyzE6u7oEP7onGk0vZRh8wfVGC2dZoy0EqX1V8qok4qHaw==", 284 | "cpu": [ 285 | "ppc64" 286 | ], 287 | "dev": true, 288 | "optional": true, 289 | "os": [ 290 | "linux" 291 | ], 292 | "engines": { 293 | "node": ">=12" 294 | } 295 | }, 296 | "node_modules/@esbuild/linux-riscv64": { 297 | "version": "0.20.1", 298 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.1.tgz", 299 | "integrity": "sha512-wpDlpE0oRKZwX+GfomcALcouqjjV8MIX8DyTrxfyCfXxoKQSDm45CZr9fanJ4F6ckD4yDEPT98SrjvLwIqUCgg==", 300 | "cpu": [ 301 | "riscv64" 302 | ], 303 | "dev": true, 304 | "optional": true, 305 | "os": [ 306 | "linux" 307 | ], 308 | "engines": { 309 | "node": ">=12" 310 | } 311 | }, 312 | "node_modules/@esbuild/linux-s390x": { 313 | "version": "0.20.1", 314 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.1.tgz", 315 | "integrity": "sha512-5BepC2Au80EohQ2dBpyTquqGCES7++p7G+7lXe1bAIvMdXm4YYcEfZtQrP4gaoZ96Wv1Ute61CEHFU7h4FMueQ==", 316 | "cpu": [ 317 | "s390x" 318 | ], 319 | "dev": true, 320 | "optional": true, 321 | "os": [ 322 | "linux" 323 | ], 324 | "engines": { 325 | "node": ">=12" 326 | } 327 | }, 328 | "node_modules/@esbuild/linux-x64": { 329 | "version": "0.20.1", 330 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.1.tgz", 331 | "integrity": "sha512-5gRPk7pKuaIB+tmH+yKd2aQTRpqlf1E4f/mC+tawIm/CGJemZcHZpp2ic8oD83nKgUPMEd0fNanrnFljiruuyA==", 332 | "cpu": [ 333 | "x64" 334 | ], 335 | "dev": true, 336 | "optional": true, 337 | "os": [ 338 | "linux" 339 | ], 340 | "engines": { 341 | "node": ">=12" 342 | } 343 | }, 344 | "node_modules/@esbuild/netbsd-x64": { 345 | "version": "0.20.1", 346 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.1.tgz", 347 | "integrity": "sha512-4fL68JdrLV2nVW2AaWZBv3XEm3Ae3NZn/7qy2KGAt3dexAgSVT+Hc97JKSZnqezgMlv9x6KV0ZkZY7UO5cNLCg==", 348 | "cpu": [ 349 | "x64" 350 | ], 351 | "dev": true, 352 | "optional": true, 353 | "os": [ 354 | "netbsd" 355 | ], 356 | "engines": { 357 | "node": ">=12" 358 | } 359 | }, 360 | "node_modules/@esbuild/openbsd-x64": { 361 | "version": "0.20.1", 362 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.1.tgz", 363 | "integrity": "sha512-GhRuXlvRE+twf2ES+8REbeCb/zeikNqwD3+6S5y5/x+DYbAQUNl0HNBs4RQJqrechS4v4MruEr8ZtAin/hK5iw==", 364 | "cpu": [ 365 | "x64" 366 | ], 367 | "dev": true, 368 | "optional": true, 369 | "os": [ 370 | "openbsd" 371 | ], 372 | "engines": { 373 | "node": ">=12" 374 | } 375 | }, 376 | "node_modules/@esbuild/sunos-x64": { 377 | "version": "0.20.1", 378 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.1.tgz", 379 | "integrity": "sha512-ZnWEyCM0G1Ex6JtsygvC3KUUrlDXqOihw8RicRuQAzw+c4f1D66YlPNNV3rkjVW90zXVsHwZYWbJh3v+oQFM9Q==", 380 | "cpu": [ 381 | "x64" 382 | ], 383 | "dev": true, 384 | "optional": true, 385 | "os": [ 386 | "sunos" 387 | ], 388 | "engines": { 389 | "node": ">=12" 390 | } 391 | }, 392 | "node_modules/@esbuild/win32-arm64": { 393 | "version": "0.20.1", 394 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.1.tgz", 395 | "integrity": "sha512-QZ6gXue0vVQY2Oon9WyLFCdSuYbXSoxaZrPuJ4c20j6ICedfsDilNPYfHLlMH7vGfU5DQR0czHLmJvH4Nzis/A==", 396 | "cpu": [ 397 | "arm64" 398 | ], 399 | "dev": true, 400 | "optional": true, 401 | "os": [ 402 | "win32" 403 | ], 404 | "engines": { 405 | "node": ">=12" 406 | } 407 | }, 408 | "node_modules/@esbuild/win32-ia32": { 409 | "version": "0.20.1", 410 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.1.tgz", 411 | "integrity": "sha512-HzcJa1NcSWTAU0MJIxOho8JftNp9YALui3o+Ny7hCh0v5f90nprly1U3Sj1Ldj/CvKKdvvFsCRvDkpsEMp4DNw==", 412 | "cpu": [ 413 | "ia32" 414 | ], 415 | "dev": true, 416 | "optional": true, 417 | "os": [ 418 | "win32" 419 | ], 420 | "engines": { 421 | "node": ">=12" 422 | } 423 | }, 424 | "node_modules/@esbuild/win32-x64": { 425 | "version": "0.20.1", 426 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.1.tgz", 427 | "integrity": "sha512-0MBh53o6XtI6ctDnRMeQ+xoCN8kD2qI1rY1KgF/xdWQwoFeKou7puvDfV8/Wv4Ctx2rRpET/gGdz3YlNtNACSA==", 428 | "cpu": [ 429 | "x64" 430 | ], 431 | "dev": true, 432 | "optional": true, 433 | "os": [ 434 | "win32" 435 | ], 436 | "engines": { 437 | "node": ">=12" 438 | } 439 | }, 440 | "node_modules/@fastify/busboy": { 441 | "version": "2.1.1", 442 | "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", 443 | "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", 444 | "engines": { 445 | "node": ">=14" 446 | } 447 | }, 448 | "node_modules/@vercel/ncc": { 449 | "version": "0.38.1", 450 | "resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.38.1.tgz", 451 | "integrity": "sha512-IBBb+iI2NLu4VQn3Vwldyi2QwaXt5+hTyh58ggAMoCGE6DJmPvwL3KPBWcJl1m9LYPChBLE980Jw+CS4Wokqxw==", 452 | "dev": true, 453 | "bin": { 454 | "ncc": "dist/ncc/cli.js" 455 | } 456 | }, 457 | "node_modules/esbuild": { 458 | "version": "0.20.1", 459 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.1.tgz", 460 | "integrity": "sha512-OJwEgrpWm/PCMsLVWXKqvcjme3bHNpOgN7Tb6cQnR5n0TPbQx1/Xrn7rqM+wn17bYeT6MGB5sn1Bh5YiGi70nA==", 461 | "dev": true, 462 | "hasInstallScript": true, 463 | "bin": { 464 | "esbuild": "bin/esbuild" 465 | }, 466 | "engines": { 467 | "node": ">=12" 468 | }, 469 | "optionalDependencies": { 470 | "@esbuild/aix-ppc64": "0.20.1", 471 | "@esbuild/android-arm": "0.20.1", 472 | "@esbuild/android-arm64": "0.20.1", 473 | "@esbuild/android-x64": "0.20.1", 474 | "@esbuild/darwin-arm64": "0.20.1", 475 | "@esbuild/darwin-x64": "0.20.1", 476 | "@esbuild/freebsd-arm64": "0.20.1", 477 | "@esbuild/freebsd-x64": "0.20.1", 478 | "@esbuild/linux-arm": "0.20.1", 479 | "@esbuild/linux-arm64": "0.20.1", 480 | "@esbuild/linux-ia32": "0.20.1", 481 | "@esbuild/linux-loong64": "0.20.1", 482 | "@esbuild/linux-mips64el": "0.20.1", 483 | "@esbuild/linux-ppc64": "0.20.1", 484 | "@esbuild/linux-riscv64": "0.20.1", 485 | "@esbuild/linux-s390x": "0.20.1", 486 | "@esbuild/linux-x64": "0.20.1", 487 | "@esbuild/netbsd-x64": "0.20.1", 488 | "@esbuild/openbsd-x64": "0.20.1", 489 | "@esbuild/sunos-x64": "0.20.1", 490 | "@esbuild/win32-arm64": "0.20.1", 491 | "@esbuild/win32-ia32": "0.20.1", 492 | "@esbuild/win32-x64": "0.20.1" 493 | } 494 | }, 495 | "node_modules/semver": { 496 | "version": "6.3.1", 497 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", 498 | "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", 499 | "bin": { 500 | "semver": "bin/semver.js" 501 | } 502 | }, 503 | "node_modules/tunnel": { 504 | "version": "0.0.6", 505 | "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", 506 | "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", 507 | "engines": { 508 | "node": ">=0.6.11 <=0.7.0 || >=0.7.3" 509 | } 510 | }, 511 | "node_modules/undici": { 512 | "version": "5.28.4", 513 | "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", 514 | "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", 515 | "dependencies": { 516 | "@fastify/busboy": "^2.0.0" 517 | }, 518 | "engines": { 519 | "node": ">=14.0" 520 | } 521 | }, 522 | "node_modules/uuid": { 523 | "version": "3.4.0", 524 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", 525 | "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", 526 | "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", 527 | "bin": { 528 | "uuid": "bin/uuid" 529 | } 530 | }, 531 | "node_modules/xhr2": { 532 | "version": "0.2.1", 533 | "resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.2.1.tgz", 534 | "integrity": "sha512-sID0rrVCqkVNUn8t6xuv9+6FViXjUVXq8H5rWOH2rz9fDNQEd4g0EA2XlcEdJXRz5BMEn4O1pJFdT+z4YHhoWw==", 535 | "engines": { 536 | "node": ">= 6" 537 | } 538 | } 539 | } 540 | } 541 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "setup-purescript", 3 | "description": "Set up a PureScript toolchain in GitHub Actions", 4 | "author": "Thomas Honeyman", 5 | "license": "MIT", 6 | "type": "module", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/thomashoneyman/setup-purescript.git" 10 | }, 11 | "scripts": { 12 | "build": "spago build --strict --censor-stats --pedantic-packages", 13 | "build:watch": "watchexec -e purs,js,yaml -- npm run build", 14 | "bundle": "spago bundle --strict --censor-stats --pedantic-packages --bundle-type module --platform node --outfile ./output/index.js && ncc build --minify update.js && mv dist/index.js dist/update.js && ncc build --minify index.js", 15 | "run-index": "node ./index.js", 16 | "run-update": "node ./update.js", 17 | "format-in-place": "purs-tidy format-in-place src/**", 18 | "check": "purs-tidy check src/**" 19 | }, 20 | "dependencies": { 21 | "@actions/core": "^1.10.1", 22 | "@actions/exec": "^1.1.1", 23 | "@actions/tool-cache": "^2.0.1", 24 | "xhr2": "^0.2.1" 25 | }, 26 | "devDependencies": { 27 | "@vercel/ncc": "^0.38.1", 28 | "esbuild": "0.20.1" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /spago.lock: -------------------------------------------------------------------------------- 1 | workspace: 2 | packages: 3 | setup-purescript: 4 | path: ./ 5 | dependencies: 6 | - aff 7 | - aff-retry 8 | - affjax 9 | - affjax-node 10 | - argonaut-codecs 11 | - argonaut-core 12 | - arrays 13 | - bifunctors 14 | - control 15 | - effect 16 | - either 17 | - enums 18 | - exceptions 19 | - foldable-traversable 20 | - foreign-object 21 | - github-actions-toolkit 22 | - integers 23 | - lists 24 | - maybe 25 | - newtype 26 | - node-buffer 27 | - node-fs 28 | - node-path 29 | - node-process 30 | - numbers 31 | - ordered-collections 32 | - parsing 33 | - partial 34 | - prelude 35 | - refs 36 | - strings 37 | - tailrec 38 | - transformers 39 | - tuples 40 | - versions 41 | test_dependencies: [] 42 | build_plan: 43 | - aff 44 | - aff-promise 45 | - aff-retry 46 | - affjax 47 | - affjax-node 48 | - argonaut-codecs 49 | - argonaut-core 50 | - arraybuffer-types 51 | - arrays 52 | - bifunctors 53 | - const 54 | - contravariant 55 | - control 56 | - datetime 57 | - distributive 58 | - effect 59 | - either 60 | - enums 61 | - exceptions 62 | - exists 63 | - foldable-traversable 64 | - foreign 65 | - foreign-object 66 | - form-urlencoded 67 | - functions 68 | - functors 69 | - gen 70 | - github-actions-toolkit 71 | - http-methods 72 | - identity 73 | - integers 74 | - invariant 75 | - js-date 76 | - js-uri 77 | - lazy 78 | - lists 79 | - maybe 80 | - media-types 81 | - newtype 82 | - node-buffer 83 | - node-event-emitter 84 | - node-fs 85 | - node-path 86 | - node-process 87 | - node-streams 88 | - nonempty 89 | - now 90 | - nullable 91 | - numbers 92 | - ordered-collections 93 | - orders 94 | - parallel 95 | - parsing 96 | - partial 97 | - posix-types 98 | - prelude 99 | - profunctor 100 | - random 101 | - record 102 | - refs 103 | - safe-coerce 104 | - st 105 | - strings 106 | - tailrec 107 | - transformers 108 | - tuples 109 | - type-equality 110 | - typelevel-prelude 111 | - unfoldable 112 | - unicode 113 | - unsafe-coerce 114 | - versions 115 | - web-dom 116 | - web-events 117 | - web-file 118 | - web-html 119 | - web-storage 120 | - web-xhr 121 | package_set: 122 | address: 123 | registry: 50.4.0 124 | compiler: ">=0.15.15 <0.16.0" 125 | content: 126 | abc-parser: 2.0.1 127 | ace: 9.1.0 128 | aff: 7.1.0 129 | aff-bus: 6.0.0 130 | aff-coroutines: 9.0.0 131 | aff-promise: 4.0.0 132 | aff-retry: 2.0.0 133 | affjax: 13.0.0 134 | affjax-node: 1.0.0 135 | affjax-web: 1.0.0 136 | ansi: 7.0.0 137 | applicative-phases: 1.0.0 138 | argonaut: 9.0.0 139 | argonaut-aeson-generic: 0.4.1 140 | argonaut-codecs: 9.1.0 141 | argonaut-core: 7.0.0 142 | argonaut-generic: 8.0.0 143 | argonaut-traversals: 10.0.0 144 | argparse-basic: 2.0.0 145 | array-builder: 0.1.2 146 | array-search: 0.5.6 147 | arraybuffer: 13.2.0 148 | arraybuffer-builder: 3.1.0 149 | arraybuffer-types: 3.0.2 150 | arrays: 7.3.0 151 | arrays-extra: 0.6.1 152 | arrays-zipper: 2.0.1 153 | ask: 1.0.0 154 | assert: 6.0.0 155 | assert-multiple: 0.3.4 156 | avar: 5.0.0 157 | b64: 0.0.8 158 | barbies: 1.0.1 159 | barlow-lens: 0.9.0 160 | bifunctors: 6.0.0 161 | bigints: 7.0.1 162 | bolson: 0.3.9 163 | bookhound: 0.1.7 164 | bower-json: 3.0.0 165 | call-by-name: 4.0.1 166 | canvas: 6.0.0 167 | canvas-action: 9.0.0 168 | cartesian: 1.0.6 169 | catenable-lists: 7.0.0 170 | chameleon: 1.0.0 171 | chameleon-halogen: 1.0.3 172 | chameleon-react-basic: 1.1.0 173 | chameleon-styled: 2.5.0 174 | chameleon-transformers: 1.0.0 175 | channel: 1.0.0 176 | checked-exceptions: 3.1.1 177 | choku: 1.0.1 178 | classless: 0.1.1 179 | classless-arbitrary: 0.1.1 180 | classless-decode-json: 0.1.1 181 | classless-encode-json: 0.1.3 182 | classnames: 2.0.0 183 | codec: 6.1.0 184 | codec-argonaut: 10.0.0 185 | codec-json: 1.1.0 186 | colors: 7.0.1 187 | concur-core: 0.5.0 188 | concur-react: 0.5.0 189 | concurrent-queues: 3.0.0 190 | console: 6.1.0 191 | const: 6.0.0 192 | contravariant: 6.0.0 193 | control: 6.0.0 194 | convertable-options: 1.0.0 195 | coroutines: 7.0.0 196 | css: 6.0.0 197 | css-frameworks: 1.0.1 198 | data-mvc: 0.0.2 199 | datetime: 6.1.0 200 | datetime-parsing: 0.2.0 201 | debug: 6.0.2 202 | decimals: 7.1.0 203 | default-values: 1.0.1 204 | deku: 0.9.23 205 | deno: 0.0.5 206 | dissect: 1.0.0 207 | distributive: 6.0.0 208 | dom-filereader: 7.0.0 209 | dom-indexed: 12.0.0 210 | dotenv: 4.0.3 211 | droplet: 0.6.0 212 | dts: 1.0.0 213 | dual-numbers: 1.0.2 214 | dynamic-buffer: 3.0.1 215 | echarts-simple: 0.0.1 216 | effect: 4.0.0 217 | either: 6.1.0 218 | elmish: 0.11.3 219 | elmish-enzyme: 0.1.1 220 | elmish-hooks: 0.10.0 221 | elmish-html: 0.8.2 222 | elmish-testing-library: 0.3.2 223 | email-validate: 7.0.0 224 | encoding: 0.0.9 225 | enums: 6.0.1 226 | env-names: 0.3.4 227 | error: 2.0.0 228 | eta-conversion: 0.3.2 229 | exceptions: 6.0.0 230 | exists: 6.0.0 231 | exitcodes: 4.0.0 232 | expect-inferred: 3.0.0 233 | fahrtwind: 2.0.0 234 | fallback: 0.1.0 235 | fast-vect: 1.2.0 236 | fetch: 4.1.0 237 | fetch-argonaut: 1.0.1 238 | fetch-core: 5.1.0 239 | fetch-yoga-json: 1.1.0 240 | fft-js: 0.1.0 241 | filterable: 5.0.0 242 | fix-functor: 0.1.0 243 | fixed-points: 7.0.0 244 | fixed-precision: 5.0.0 245 | flame: 1.3.0 246 | float32: 2.0.0 247 | fmt: 0.2.1 248 | foldable-traversable: 6.0.0 249 | foldable-traversable-extra: 0.0.6 250 | foreign: 7.0.0 251 | foreign-object: 4.1.0 252 | foreign-readwrite: 3.4.0 253 | forgetmenot: 0.1.0 254 | fork: 6.0.0 255 | form-urlencoded: 7.0.0 256 | formatters: 7.0.0 257 | framer-motion: 1.0.1 258 | free: 7.1.0 259 | freeap: 7.0.0 260 | freer-free: 0.0.1 261 | freet: 7.0.0 262 | functions: 6.0.0 263 | functor1: 3.0.0 264 | functors: 5.0.0 265 | fuzzy: 0.4.0 266 | gen: 4.0.0 267 | generate-values: 1.0.1 268 | generic-router: 0.0.1 269 | geojson: 0.0.5 270 | geometry-plane: 1.0.3 271 | gojs: 0.1.1 272 | grain: 3.0.0 273 | grain-router: 3.0.0 274 | grain-virtualized: 3.0.0 275 | graphs: 8.1.0 276 | group: 4.1.1 277 | halogen: 7.0.0 278 | halogen-bootstrap5: 5.3.2 279 | halogen-canvas: 1.0.0 280 | halogen-css: 10.0.0 281 | halogen-echarts-simple: 0.0.4 282 | halogen-formless: 4.0.3 283 | halogen-helix: 1.0.0 284 | halogen-hooks: 0.6.3 285 | halogen-hooks-extra: 0.9.0 286 | halogen-infinite-scroll: 1.1.0 287 | halogen-store: 0.5.4 288 | halogen-storybook: 2.0.0 289 | halogen-subscriptions: 2.0.0 290 | halogen-svg-elems: 8.0.0 291 | halogen-typewriter: 1.0.4 292 | halogen-vdom: 8.0.0 293 | halogen-vdom-string-renderer: 0.5.0 294 | halogen-xterm: 2.0.0 295 | heckin: 2.0.1 296 | heterogeneous: 0.6.0 297 | homogeneous: 0.4.0 298 | http-methods: 6.0.0 299 | httpurple: 4.0.0 300 | humdrum: 0.0.1 301 | hyrule: 2.3.8 302 | identity: 6.0.0 303 | identy: 4.0.1 304 | indexed-db: 1.0.0 305 | indexed-monad: 3.0.0 306 | int64: 3.0.0 307 | integers: 6.0.0 308 | interpolate: 5.0.2 309 | intersection-observer: 1.0.1 310 | invariant: 6.0.0 311 | jarilo: 1.0.1 312 | jelly: 0.10.0 313 | jelly-router: 0.3.0 314 | jelly-signal: 0.4.0 315 | jest: 1.0.0 316 | js-abort-controller: 1.0.0 317 | js-bigints: 2.2.1 318 | js-date: 8.0.0 319 | js-fetch: 0.2.1 320 | js-fileio: 3.0.0 321 | js-intl: 1.0.4 322 | js-iterators: 0.1.1 323 | js-maps: 0.1.2 324 | js-promise: 1.0.0 325 | js-promise-aff: 1.0.0 326 | js-timers: 6.1.0 327 | js-uri: 3.1.0 328 | json: 1.0.0 329 | json-codecs: 5.0.0 330 | justifill: 0.5.0 331 | jwt: 0.0.9 332 | labeled-data: 0.2.0 333 | language-cst-parser: 0.14.0 334 | lazy: 6.0.0 335 | lazy-joe: 1.0.0 336 | lcg: 4.0.0 337 | leibniz: 5.0.0 338 | leveldb: 1.0.1 339 | liminal: 1.0.1 340 | linalg: 6.0.0 341 | lists: 7.0.0 342 | literals: 1.0.2 343 | logging: 3.0.0 344 | logging-journald: 0.4.0 345 | lumi-components: 18.0.0 346 | machines: 7.0.0 347 | maps-eager: 0.4.1 348 | marionette: 1.0.0 349 | marionette-react-basic-hooks: 0.1.1 350 | marked: 0.1.0 351 | matrices: 5.0.1 352 | matryoshka: 1.0.0 353 | maybe: 6.0.0 354 | media-types: 6.0.0 355 | meowclient: 1.0.0 356 | midi: 4.0.0 357 | milkis: 9.0.0 358 | minibench: 4.0.1 359 | mmorph: 7.0.0 360 | monad-control: 5.0.0 361 | monad-logger: 1.3.1 362 | monad-loops: 0.5.0 363 | monad-unlift: 1.0.1 364 | monoid-extras: 0.0.1 365 | monoidal: 0.16.0 366 | morello: 0.4.0 367 | mote: 3.0.0 368 | motsunabe: 2.0.0 369 | mvc: 0.0.1 370 | mysql: 6.0.1 371 | n3: 0.1.0 372 | nano-id: 1.1.0 373 | nanoid: 0.1.0 374 | naturals: 3.0.0 375 | nested-functor: 0.2.1 376 | newtype: 5.0.0 377 | nextjs: 0.1.1 378 | nextui: 0.2.0 379 | node-buffer: 9.0.0 380 | node-child-process: 11.1.0 381 | node-event-emitter: 3.0.0 382 | node-execa: 5.0.0 383 | node-fs: 9.1.0 384 | node-glob-basic: 1.3.0 385 | node-http: 9.1.0 386 | node-http2: 1.1.1 387 | node-human-signals: 1.0.0 388 | node-net: 5.1.0 389 | node-os: 5.1.0 390 | node-path: 5.0.0 391 | node-process: 11.2.0 392 | node-readline: 8.1.0 393 | node-sqlite3: 8.0.0 394 | node-streams: 9.0.0 395 | node-tls: 0.3.1 396 | node-url: 7.0.1 397 | node-zlib: 0.4.0 398 | nonempty: 7.0.0 399 | now: 6.0.0 400 | npm-package-json: 2.0.0 401 | nullable: 6.0.0 402 | numberfield: 0.1.0 403 | numbers: 9.0.1 404 | oak: 3.1.1 405 | oak-debug: 1.2.2 406 | object-maps: 0.3.0 407 | ocarina: 1.5.4 408 | open-folds: 6.3.0 409 | open-memoize: 6.1.0 410 | open-pairing: 6.1.0 411 | options: 7.0.0 412 | optparse: 5.0.1 413 | ordered-collections: 3.1.1 414 | ordered-set: 0.4.0 415 | orders: 6.0.0 416 | owoify: 1.2.0 417 | pairs: 9.0.1 418 | parallel: 7.0.0 419 | parsing: 10.2.0 420 | parsing-dataview: 3.2.4 421 | partial: 4.0.0 422 | pathy: 9.0.0 423 | pha: 0.13.0 424 | phaser: 0.7.0 425 | phylio: 1.1.2 426 | pipes: 8.0.0 427 | pirates-charm: 0.0.1 428 | pmock: 0.9.0 429 | point-free: 1.0.0 430 | pointed-list: 0.5.1 431 | polymorphic-vectors: 4.0.0 432 | posix-types: 6.0.0 433 | precise: 6.0.0 434 | precise-datetime: 7.0.0 435 | prelude: 6.0.1 436 | prettier-printer: 3.0.0 437 | profunctor: 6.0.1 438 | profunctor-lenses: 8.0.0 439 | protobuf: 4.3.0 440 | psa-utils: 8.0.0 441 | psci-support: 6.0.0 442 | punycode: 1.0.0 443 | qualified-do: 2.2.0 444 | quantities: 12.2.0 445 | quickcheck: 8.0.1 446 | quickcheck-combinators: 0.1.3 447 | quickcheck-laws: 7.0.0 448 | quickcheck-utf8: 0.0.0 449 | random: 6.0.0 450 | rationals: 6.0.0 451 | rdf: 0.1.0 452 | react: 11.0.0 453 | react-aria: 0.2.0 454 | react-basic: 17.0.0 455 | react-basic-classic: 3.0.0 456 | react-basic-dnd: 10.1.0 457 | react-basic-dom: 6.1.0 458 | react-basic-emotion: 7.1.0 459 | react-basic-hooks: 8.2.0 460 | react-basic-storybook: 2.0.0 461 | react-dom: 8.0.0 462 | react-halo: 3.0.0 463 | react-icons: 1.1.4 464 | react-markdown: 0.1.0 465 | react-testing-library: 4.0.1 466 | react-virtuoso: 1.0.0 467 | read: 1.0.1 468 | recharts: 1.1.0 469 | record: 4.0.0 470 | record-extra: 5.0.1 471 | record-ptional-fields: 0.1.2 472 | record-studio: 1.0.4 473 | refs: 6.0.0 474 | remotedata: 5.0.1 475 | resize-observer: 1.0.0 476 | resource: 2.0.1 477 | resourcet: 1.0.0 478 | result: 1.0.3 479 | return: 0.2.0 480 | ring-modules: 5.0.1 481 | rito: 0.3.4 482 | rough-notation: 1.0.2 483 | routing: 11.0.0 484 | routing-duplex: 0.7.0 485 | run: 5.0.0 486 | safe-coerce: 2.0.0 487 | safely: 4.0.1 488 | school-of-music: 1.3.0 489 | selection-foldable: 0.2.0 490 | selective-functors: 1.0.1 491 | semirings: 7.0.0 492 | signal: 13.0.0 493 | simple-emitter: 3.0.1 494 | simple-i18n: 2.0.1 495 | simple-json: 9.0.0 496 | simple-ulid: 3.0.0 497 | sized-matrices: 1.0.0 498 | sized-vectors: 5.0.2 499 | slug: 3.0.8 500 | small-ffi: 4.0.1 501 | soundfonts: 4.1.0 502 | sparse-matrices: 1.3.0 503 | sparse-polynomials: 2.0.5 504 | spec: 7.6.0 505 | spec-mocha: 5.1.0 506 | spec-quickcheck: 5.0.0 507 | splitmix: 2.1.0 508 | ssrs: 1.0.0 509 | st: 6.2.0 510 | statistics: 0.3.2 511 | strictlypositiveint: 1.0.1 512 | string-parsers: 8.0.0 513 | strings: 6.0.1 514 | strings-extra: 4.0.0 515 | stringutils: 0.0.12 516 | substitute: 0.2.3 517 | supply: 0.2.0 518 | svg-parser: 3.0.0 519 | systemd-journald: 0.3.0 520 | tagged: 4.0.2 521 | tailrec: 6.1.0 522 | tecton: 0.2.1 523 | tecton-halogen: 0.2.0 524 | test-unit: 17.0.0 525 | thermite: 6.3.1 526 | thermite-dom: 0.3.1 527 | these: 6.0.0 528 | transformation-matrix: 1.0.1 529 | transformers: 6.0.0 530 | tree-rose: 4.0.2 531 | ts-bridge: 4.0.0 532 | tuples: 7.0.0 533 | two-or-more: 1.0.0 534 | type-equality: 4.0.1 535 | typedenv: 2.0.1 536 | typelevel: 6.0.0 537 | typelevel-lists: 2.1.0 538 | typelevel-peano: 1.0.1 539 | typelevel-prelude: 7.0.0 540 | typelevel-regex: 0.0.3 541 | typelevel-rows: 0.1.0 542 | uint: 7.0.0 543 | ulid: 3.0.1 544 | uncurried-transformers: 1.1.0 545 | undefined: 2.0.0 546 | undefined-is-not-a-problem: 1.1.0 547 | unfoldable: 6.0.0 548 | unicode: 6.0.0 549 | unique: 0.6.1 550 | unlift: 1.0.1 551 | unordered-collections: 3.1.0 552 | unsafe-coerce: 6.0.0 553 | unsafe-reference: 5.0.0 554 | untagged-to-tagged: 0.1.4 555 | untagged-union: 1.0.0 556 | uri: 9.0.0 557 | uuid: 9.0.0 558 | uuidv4: 1.0.0 559 | validation: 6.0.0 560 | variant: 8.0.0 561 | variant-encodings: 2.0.0 562 | vectorfield: 1.0.1 563 | vectors: 2.1.0 564 | versions: 7.0.0 565 | visx: 0.0.2 566 | web-clipboard: 5.0.0 567 | web-cssom: 2.0.0 568 | web-cssom-view: 0.1.0 569 | web-dom: 6.0.0 570 | web-dom-parser: 8.0.0 571 | web-dom-xpath: 3.0.0 572 | web-encoding: 3.0.0 573 | web-events: 4.0.0 574 | web-fetch: 4.0.1 575 | web-file: 4.0.0 576 | web-geometry: 0.1.0 577 | web-html: 4.1.0 578 | web-pointerevents: 2.0.0 579 | web-proletarian: 1.0.0 580 | web-promise: 3.2.0 581 | web-resize-observer: 2.1.0 582 | web-router: 1.0.0 583 | web-socket: 4.0.0 584 | web-storage: 5.0.0 585 | web-streams: 4.0.0 586 | web-touchevents: 4.0.0 587 | web-uievents: 5.0.0 588 | web-url: 2.0.0 589 | web-workers: 1.1.0 590 | web-xhr: 5.0.1 591 | webextension-polyfill: 0.1.0 592 | webgpu: 0.0.1 593 | which: 2.0.0 594 | xterm: 1.0.0 595 | yoga-fetch: 1.0.1 596 | yoga-json: 5.1.0 597 | yoga-om: 0.1.0 598 | yoga-postgres: 6.0.0 599 | yoga-tree: 1.0.0 600 | z3: 0.0.2 601 | zipperarray: 2.0.0 602 | extra_packages: 603 | github-actions-toolkit: 604 | git: https://github.com/srghma/purescript-github-actions-toolkit.git 605 | ref: main 606 | packages: 607 | aff: 608 | type: registry 609 | version: 7.1.0 610 | integrity: sha256-7hOC6uQO9XBAI5FD8F33ChLjFAiZVfd4BJMqlMh7TNU= 611 | dependencies: 612 | - arrays 613 | - bifunctors 614 | - control 615 | - datetime 616 | - effect 617 | - either 618 | - exceptions 619 | - foldable-traversable 620 | - functions 621 | - maybe 622 | - newtype 623 | - parallel 624 | - prelude 625 | - refs 626 | - tailrec 627 | - transformers 628 | - unsafe-coerce 629 | aff-promise: 630 | type: registry 631 | version: 4.0.0 632 | integrity: sha256-Kq5EupbUpXeUXx4JqGQE7/RTTz/H6idzWhsocwlEFhM= 633 | dependencies: 634 | - aff 635 | - foreign 636 | aff-retry: 637 | type: registry 638 | version: 2.0.0 639 | integrity: sha256-01Vi8gUS2cEIToulcK6FAA4REEHvgQIUR7mcW5EY3rY= 640 | dependencies: 641 | - aff 642 | - arrays 643 | - datetime 644 | - effect 645 | - either 646 | - exceptions 647 | - integers 648 | - maybe 649 | - newtype 650 | - numbers 651 | - prelude 652 | - random 653 | - transformers 654 | affjax: 655 | type: registry 656 | version: 13.0.0 657 | integrity: sha256-blYfaoW4FYIrIdvmT4sB7nN7BathFaEfZuiVLPmHJOo= 658 | dependencies: 659 | - aff 660 | - argonaut-core 661 | - arraybuffer-types 662 | - foreign 663 | - form-urlencoded 664 | - http-methods 665 | - integers 666 | - media-types 667 | - nullable 668 | - refs 669 | - unsafe-coerce 670 | - web-xhr 671 | affjax-node: 672 | type: registry 673 | version: 1.0.0 674 | integrity: sha256-NcmRTXJxJzgHuKoLh+36yA8UejkfouYcX3uevT+Trjc= 675 | dependencies: 676 | - aff 677 | - affjax 678 | - either 679 | - maybe 680 | - prelude 681 | argonaut-codecs: 682 | type: registry 683 | version: 9.1.0 684 | integrity: sha256-N6efXByUeg848ompEqJfVvZuZPfdRYDGlTDFn0G0Oh8= 685 | dependencies: 686 | - argonaut-core 687 | - arrays 688 | - effect 689 | - foreign-object 690 | - identity 691 | - integers 692 | - maybe 693 | - nonempty 694 | - ordered-collections 695 | - prelude 696 | - record 697 | argonaut-core: 698 | type: registry 699 | version: 7.0.0 700 | integrity: sha256-RC82GfAjItydxrO24cdX373KHVZiLqybu19b5X8u7B4= 701 | dependencies: 702 | - arrays 703 | - control 704 | - either 705 | - foreign-object 706 | - functions 707 | - gen 708 | - maybe 709 | - nonempty 710 | - prelude 711 | - strings 712 | - tailrec 713 | arraybuffer-types: 714 | type: registry 715 | version: 3.0.2 716 | integrity: sha256-mQKokysYVkooS4uXbO+yovmV/s8b138Ws3zQvOwIHRA= 717 | dependencies: [] 718 | arrays: 719 | type: registry 720 | version: 7.3.0 721 | integrity: sha256-tmcklBlc/muUtUfr9RapdCPwnlQeB3aSrC4dK85gQlc= 722 | dependencies: 723 | - bifunctors 724 | - control 725 | - foldable-traversable 726 | - functions 727 | - maybe 728 | - nonempty 729 | - partial 730 | - prelude 731 | - safe-coerce 732 | - st 733 | - tailrec 734 | - tuples 735 | - unfoldable 736 | - unsafe-coerce 737 | bifunctors: 738 | type: registry 739 | version: 6.0.0 740 | integrity: sha256-/gZwC9YhNxZNQpnHa5BIYerCGM2jeX9ukZiEvYxm5Nw= 741 | dependencies: 742 | - const 743 | - either 744 | - newtype 745 | - prelude 746 | - tuples 747 | const: 748 | type: registry 749 | version: 6.0.0 750 | integrity: sha256-tNrxDW8D8H4jdHE2HiPzpLy08zkzJMmGHdRqt5BQuTc= 751 | dependencies: 752 | - invariant 753 | - newtype 754 | - prelude 755 | contravariant: 756 | type: registry 757 | version: 6.0.0 758 | integrity: sha256-TP+ooAp3vvmdjfQsQJSichF5B4BPDHp3wAJoWchip6c= 759 | dependencies: 760 | - const 761 | - either 762 | - newtype 763 | - prelude 764 | - tuples 765 | control: 766 | type: registry 767 | version: 6.0.0 768 | integrity: sha256-sH7Pg9E96JCPF9PIA6oQ8+BjTyO/BH1ZuE/bOcyj4Jk= 769 | dependencies: 770 | - newtype 771 | - prelude 772 | datetime: 773 | type: registry 774 | version: 6.1.0 775 | integrity: sha256-g/5X5BBegQWLpI9IWD+sY6mcaYpzzlW5lz5NBzaMtyI= 776 | dependencies: 777 | - bifunctors 778 | - control 779 | - either 780 | - enums 781 | - foldable-traversable 782 | - functions 783 | - gen 784 | - integers 785 | - lists 786 | - maybe 787 | - newtype 788 | - numbers 789 | - ordered-collections 790 | - partial 791 | - prelude 792 | - tuples 793 | distributive: 794 | type: registry 795 | version: 6.0.0 796 | integrity: sha256-HTDdmEnzigMl+02SJB88j+gAXDx9VKsbvR4MJGDPbOQ= 797 | dependencies: 798 | - identity 799 | - newtype 800 | - prelude 801 | - tuples 802 | - type-equality 803 | effect: 804 | type: registry 805 | version: 4.0.0 806 | integrity: sha256-eBtZu+HZcMa5HilvI6kaDyVX3ji8p0W9MGKy2K4T6+M= 807 | dependencies: 808 | - prelude 809 | either: 810 | type: registry 811 | version: 6.1.0 812 | integrity: sha256-6hgTPisnMWVwQivOu2PKYcH8uqjEOOqDyaDQVUchTpY= 813 | dependencies: 814 | - control 815 | - invariant 816 | - maybe 817 | - prelude 818 | enums: 819 | type: registry 820 | version: 6.0.1 821 | integrity: sha256-HWaD73JFLorc4A6trKIRUeDMdzE+GpkJaEOM1nTNkC8= 822 | dependencies: 823 | - control 824 | - either 825 | - gen 826 | - maybe 827 | - newtype 828 | - nonempty 829 | - partial 830 | - prelude 831 | - tuples 832 | - unfoldable 833 | exceptions: 834 | type: registry 835 | version: 6.0.0 836 | integrity: sha256-y/xTAEIZIARCE+50/u1di0ncebJ+CIwNOLswyOWzMTw= 837 | dependencies: 838 | - effect 839 | - either 840 | - maybe 841 | - prelude 842 | exists: 843 | type: registry 844 | version: 6.0.0 845 | integrity: sha256-A0JQHpTfo1dNOj9U5/Fd3xndlRSE0g2IQWOGor2yXn8= 846 | dependencies: 847 | - unsafe-coerce 848 | foldable-traversable: 849 | type: registry 850 | version: 6.0.0 851 | integrity: sha256-fLeqRYM4jUrZD5H4WqcwUgzU7XfYkzO4zhgtNc3jcWM= 852 | dependencies: 853 | - bifunctors 854 | - const 855 | - control 856 | - either 857 | - functors 858 | - identity 859 | - maybe 860 | - newtype 861 | - orders 862 | - prelude 863 | - tuples 864 | foreign: 865 | type: registry 866 | version: 7.0.0 867 | integrity: sha256-1ORiqoS3HW+qfwSZAppHPWy4/6AQysxZ2t29jcdUMNA= 868 | dependencies: 869 | - either 870 | - functions 871 | - identity 872 | - integers 873 | - lists 874 | - maybe 875 | - prelude 876 | - strings 877 | - transformers 878 | foreign-object: 879 | type: registry 880 | version: 4.1.0 881 | integrity: sha256-q24okj6mT+yGHYQ+ei/pYPj5ih6sTbu7eDv/WU56JVo= 882 | dependencies: 883 | - arrays 884 | - foldable-traversable 885 | - functions 886 | - gen 887 | - lists 888 | - maybe 889 | - prelude 890 | - st 891 | - tailrec 892 | - tuples 893 | - typelevel-prelude 894 | - unfoldable 895 | form-urlencoded: 896 | type: registry 897 | version: 7.0.0 898 | integrity: sha256-WUzk8DTjrbPVHKZ5w7XpPBO6ci6xFhvYguHp6RvX+18= 899 | dependencies: 900 | - foldable-traversable 901 | - js-uri 902 | - maybe 903 | - newtype 904 | - prelude 905 | - strings 906 | - tuples 907 | functions: 908 | type: registry 909 | version: 6.0.0 910 | integrity: sha256-adMyJNEnhGde2unHHAP79gPtlNjNqzgLB8arEOn9hLI= 911 | dependencies: 912 | - prelude 913 | functors: 914 | type: registry 915 | version: 5.0.0 916 | integrity: sha256-zfPWWYisbD84MqwpJSZFlvM6v86McM68ob8p9s27ywU= 917 | dependencies: 918 | - bifunctors 919 | - const 920 | - contravariant 921 | - control 922 | - distributive 923 | - either 924 | - invariant 925 | - maybe 926 | - newtype 927 | - prelude 928 | - profunctor 929 | - tuples 930 | - unsafe-coerce 931 | gen: 932 | type: registry 933 | version: 4.0.0 934 | integrity: sha256-f7yzAXWwr+xnaqEOcvyO3ezKdoes8+WXWdXIHDBCAPI= 935 | dependencies: 936 | - either 937 | - foldable-traversable 938 | - identity 939 | - maybe 940 | - newtype 941 | - nonempty 942 | - prelude 943 | - tailrec 944 | - tuples 945 | - unfoldable 946 | github-actions-toolkit: 947 | type: git 948 | url: https://github.com/srghma/purescript-github-actions-toolkit.git 949 | rev: 5a56f43c2a1a482368fe635ef5342cdd7e07663c 950 | dependencies: 951 | - aff 952 | - aff-promise 953 | - control 954 | - effect 955 | - either 956 | - exceptions 957 | - foreign-object 958 | - maybe 959 | - node-buffer 960 | - node-path 961 | - node-streams 962 | - nullable 963 | - prelude 964 | - transformers 965 | http-methods: 966 | type: registry 967 | version: 6.0.0 968 | integrity: sha256-Orr7rbDGcp7qoqmUMXPRMjBx+C4jqOQcFe9+gE3nMgU= 969 | dependencies: 970 | - either 971 | - prelude 972 | - strings 973 | identity: 974 | type: registry 975 | version: 6.0.0 976 | integrity: sha256-4wY0XZbAksjY6UAg99WkuKyJlQlWAfTi2ssadH0wVMY= 977 | dependencies: 978 | - control 979 | - invariant 980 | - newtype 981 | - prelude 982 | integers: 983 | type: registry 984 | version: 6.0.0 985 | integrity: sha256-sf+sK26R1hzwl3NhXR7WAu9zCDjQnfoXwcyGoseX158= 986 | dependencies: 987 | - maybe 988 | - numbers 989 | - prelude 990 | invariant: 991 | type: registry 992 | version: 6.0.0 993 | integrity: sha256-RGWWyYrz0Hs1KjPDA+87Kia67ZFBhfJ5lMGOMCEFoLo= 994 | dependencies: 995 | - control 996 | - prelude 997 | js-date: 998 | type: registry 999 | version: 8.0.0 1000 | integrity: sha256-6TVF4DWg5JL+jRAsoMssYw8rgOVALMUHT1CuNZt8NRo= 1001 | dependencies: 1002 | - datetime 1003 | - effect 1004 | - exceptions 1005 | - foreign 1006 | - integers 1007 | - now 1008 | js-uri: 1009 | type: registry 1010 | version: 3.1.0 1011 | integrity: sha256-3p0ynHveCJmC2CXze+eMBdW/2l5e953Q8XMAKz+jxUo= 1012 | dependencies: 1013 | - functions 1014 | - maybe 1015 | lazy: 1016 | type: registry 1017 | version: 6.0.0 1018 | integrity: sha256-lMsfFOnlqfe4KzRRiW8ot5ge6HtcU3Eyh2XkXcP5IgU= 1019 | dependencies: 1020 | - control 1021 | - foldable-traversable 1022 | - invariant 1023 | - prelude 1024 | lists: 1025 | type: registry 1026 | version: 7.0.0 1027 | integrity: sha256-EKF15qYqucuXP2lT/xPxhqy58f0FFT6KHdIB/yBOayI= 1028 | dependencies: 1029 | - bifunctors 1030 | - control 1031 | - foldable-traversable 1032 | - lazy 1033 | - maybe 1034 | - newtype 1035 | - nonempty 1036 | - partial 1037 | - prelude 1038 | - tailrec 1039 | - tuples 1040 | - unfoldable 1041 | maybe: 1042 | type: registry 1043 | version: 6.0.0 1044 | integrity: sha256-5cCIb0wPwbat2PRkQhUeZO0jcAmf8jCt2qE0wbC3v2Q= 1045 | dependencies: 1046 | - control 1047 | - invariant 1048 | - newtype 1049 | - prelude 1050 | media-types: 1051 | type: registry 1052 | version: 6.0.0 1053 | integrity: sha256-n/4FoGBasbVSYscGVRSyBunQ6CZbL3jsYL+Lp01mc9k= 1054 | dependencies: 1055 | - newtype 1056 | - prelude 1057 | newtype: 1058 | type: registry 1059 | version: 5.0.0 1060 | integrity: sha256-gdrQu8oGe9eZE6L3wOI8ql/igOg+zEGB5ITh2g+uttw= 1061 | dependencies: 1062 | - prelude 1063 | - safe-coerce 1064 | node-buffer: 1065 | type: registry 1066 | version: 9.0.0 1067 | integrity: sha256-PWE2DJ5ruBLCmeA/fUiuySEFmUJ/VuRfyrnCuVZBlu4= 1068 | dependencies: 1069 | - arraybuffer-types 1070 | - effect 1071 | - maybe 1072 | - nullable 1073 | - st 1074 | - unsafe-coerce 1075 | node-event-emitter: 1076 | type: registry 1077 | version: 3.0.0 1078 | integrity: sha256-Qw0MjsT4xRH2j2i4K8JmRjcMKnH5z1Cw39t00q4LE4w= 1079 | dependencies: 1080 | - effect 1081 | - either 1082 | - functions 1083 | - maybe 1084 | - nullable 1085 | - prelude 1086 | - unsafe-coerce 1087 | node-fs: 1088 | type: registry 1089 | version: 9.1.0 1090 | integrity: sha256-TzhvGdrwcM0bazDvrWSqh+M/H8GKYf1Na6aGm2Qg4+c= 1091 | dependencies: 1092 | - datetime 1093 | - effect 1094 | - either 1095 | - enums 1096 | - exceptions 1097 | - functions 1098 | - integers 1099 | - js-date 1100 | - maybe 1101 | - node-buffer 1102 | - node-path 1103 | - node-streams 1104 | - nullable 1105 | - partial 1106 | - prelude 1107 | - strings 1108 | - unsafe-coerce 1109 | node-path: 1110 | type: registry 1111 | version: 5.0.0 1112 | integrity: sha256-pd82nQ+2l5UThzaxPdKttgDt7xlsgIDLpPG0yxDEdyE= 1113 | dependencies: 1114 | - effect 1115 | node-process: 1116 | type: registry 1117 | version: 11.2.0 1118 | integrity: sha256-+2MQDYChjGbVbapCyJtuWYwD41jk+BntF/kcOTKBMVs= 1119 | dependencies: 1120 | - effect 1121 | - foreign 1122 | - foreign-object 1123 | - maybe 1124 | - node-event-emitter 1125 | - node-streams 1126 | - posix-types 1127 | - prelude 1128 | - unsafe-coerce 1129 | node-streams: 1130 | type: registry 1131 | version: 9.0.0 1132 | integrity: sha256-2n6dq7YWleTDmD1Kur/ul7Cn08IvWrScgPf+0PgX2TQ= 1133 | dependencies: 1134 | - aff 1135 | - effect 1136 | - either 1137 | - exceptions 1138 | - node-buffer 1139 | - node-event-emitter 1140 | - nullable 1141 | - prelude 1142 | nonempty: 1143 | type: registry 1144 | version: 7.0.0 1145 | integrity: sha256-54ablJZUHGvvlTJzi3oXyPCuvY6zsrWJuH/dMJ/MFLs= 1146 | dependencies: 1147 | - control 1148 | - foldable-traversable 1149 | - maybe 1150 | - prelude 1151 | - tuples 1152 | - unfoldable 1153 | now: 1154 | type: registry 1155 | version: 6.0.0 1156 | integrity: sha256-xZ7x37ZMREfs6GCDw/h+FaKHV/3sPWmtqBZRGTxybQY= 1157 | dependencies: 1158 | - datetime 1159 | - effect 1160 | nullable: 1161 | type: registry 1162 | version: 6.0.0 1163 | integrity: sha256-yiGBVl3AD+Guy4kNWWeN+zl1gCiJK+oeIFtZtPCw4+o= 1164 | dependencies: 1165 | - effect 1166 | - functions 1167 | - maybe 1168 | numbers: 1169 | type: registry 1170 | version: 9.0.1 1171 | integrity: sha256-/9M6aeMDBdB4cwYDeJvLFprAHZ49EbtKQLIJsneXLIk= 1172 | dependencies: 1173 | - functions 1174 | - maybe 1175 | ordered-collections: 1176 | type: registry 1177 | version: 3.1.1 1178 | integrity: sha256-boSYHmlz4aSbwsNN4VxiwCStc0t+y1F7BXmBS+1JNtI= 1179 | dependencies: 1180 | - arrays 1181 | - foldable-traversable 1182 | - gen 1183 | - lists 1184 | - maybe 1185 | - partial 1186 | - prelude 1187 | - st 1188 | - tailrec 1189 | - tuples 1190 | - unfoldable 1191 | orders: 1192 | type: registry 1193 | version: 6.0.0 1194 | integrity: sha256-nBA0g3/ai0euH8q9pSbGqk53W2q6agm/dECZTHcoink= 1195 | dependencies: 1196 | - newtype 1197 | - prelude 1198 | parallel: 1199 | type: registry 1200 | version: 7.0.0 1201 | integrity: sha256-gUC9i4Txnx9K9RcMLsjujbwZz6BB1bnE2MLvw4GIw5o= 1202 | dependencies: 1203 | - control 1204 | - effect 1205 | - either 1206 | - foldable-traversable 1207 | - functors 1208 | - maybe 1209 | - newtype 1210 | - prelude 1211 | - profunctor 1212 | - refs 1213 | - transformers 1214 | parsing: 1215 | type: registry 1216 | version: 10.2.0 1217 | integrity: sha256-ZDIdMFAKkst57x6BVa1aUWJnS8smoZnXsZ339Aq1mPA= 1218 | dependencies: 1219 | - arrays 1220 | - control 1221 | - effect 1222 | - either 1223 | - enums 1224 | - foldable-traversable 1225 | - functions 1226 | - identity 1227 | - integers 1228 | - lazy 1229 | - lists 1230 | - maybe 1231 | - newtype 1232 | - nullable 1233 | - numbers 1234 | - partial 1235 | - prelude 1236 | - st 1237 | - strings 1238 | - tailrec 1239 | - transformers 1240 | - tuples 1241 | - unfoldable 1242 | - unicode 1243 | - unsafe-coerce 1244 | partial: 1245 | type: registry 1246 | version: 4.0.0 1247 | integrity: sha256-fwXerld6Xw1VkReh8yeQsdtLVrjfGiVuC5bA1Wyo/J4= 1248 | dependencies: [] 1249 | posix-types: 1250 | type: registry 1251 | version: 6.0.0 1252 | integrity: sha256-ZfFz8RR1lee/o/Prccyeut3Q+9tYd08mlR72sIh6GzA= 1253 | dependencies: 1254 | - maybe 1255 | - prelude 1256 | prelude: 1257 | type: registry 1258 | version: 6.0.1 1259 | integrity: sha256-o8p6SLYmVPqzXZhQFd2hGAWEwBoXl1swxLG/scpJ0V0= 1260 | dependencies: [] 1261 | profunctor: 1262 | type: registry 1263 | version: 6.0.1 1264 | integrity: sha256-E58hSYdJvF2Qjf9dnWLPlJKh2Z2fLfFLkQoYi16vsFk= 1265 | dependencies: 1266 | - control 1267 | - distributive 1268 | - either 1269 | - exists 1270 | - invariant 1271 | - newtype 1272 | - prelude 1273 | - tuples 1274 | random: 1275 | type: registry 1276 | version: 6.0.0 1277 | integrity: sha256-CJ611a35MPCE7XQMp0rdC6MCn76znlhisiCRgboAG+Q= 1278 | dependencies: 1279 | - effect 1280 | - integers 1281 | record: 1282 | type: registry 1283 | version: 4.0.0 1284 | integrity: sha256-Za5U85bTRJEfGK5Sk4hM41oXy84YQI0I8TL3WUn1Qzg= 1285 | dependencies: 1286 | - functions 1287 | - prelude 1288 | - unsafe-coerce 1289 | refs: 1290 | type: registry 1291 | version: 6.0.0 1292 | integrity: sha256-Vgwne7jIbD3ZMoLNNETLT8Litw6lIYo3MfYNdtYWj9s= 1293 | dependencies: 1294 | - effect 1295 | - prelude 1296 | safe-coerce: 1297 | type: registry 1298 | version: 2.0.0 1299 | integrity: sha256-a1ibQkiUcbODbLE/WAq7Ttbbh9ex+x33VCQ7GngKudU= 1300 | dependencies: 1301 | - unsafe-coerce 1302 | st: 1303 | type: registry 1304 | version: 6.2.0 1305 | integrity: sha256-z9X0WsOUlPwNx9GlCC+YccCyz8MejC8Wb0C4+9fiBRY= 1306 | dependencies: 1307 | - partial 1308 | - prelude 1309 | - tailrec 1310 | - unsafe-coerce 1311 | strings: 1312 | type: registry 1313 | version: 6.0.1 1314 | integrity: sha256-WssD3DbX4OPzxSdjvRMX0yvc9+pS7n5gyPv5I2Trb7k= 1315 | dependencies: 1316 | - arrays 1317 | - control 1318 | - either 1319 | - enums 1320 | - foldable-traversable 1321 | - gen 1322 | - integers 1323 | - maybe 1324 | - newtype 1325 | - nonempty 1326 | - partial 1327 | - prelude 1328 | - tailrec 1329 | - tuples 1330 | - unfoldable 1331 | - unsafe-coerce 1332 | tailrec: 1333 | type: registry 1334 | version: 6.1.0 1335 | integrity: sha256-Xx19ECVDRrDWpz9D2GxQHHV89vd61dnXxQm0IcYQHGk= 1336 | dependencies: 1337 | - bifunctors 1338 | - effect 1339 | - either 1340 | - identity 1341 | - maybe 1342 | - partial 1343 | - prelude 1344 | - refs 1345 | transformers: 1346 | type: registry 1347 | version: 6.0.0 1348 | integrity: sha256-Pzw40HjthX77tdPAYzjx43LK3X5Bb7ZspYAp27wksFA= 1349 | dependencies: 1350 | - control 1351 | - distributive 1352 | - effect 1353 | - either 1354 | - exceptions 1355 | - foldable-traversable 1356 | - identity 1357 | - lazy 1358 | - maybe 1359 | - newtype 1360 | - prelude 1361 | - tailrec 1362 | - tuples 1363 | - unfoldable 1364 | tuples: 1365 | type: registry 1366 | version: 7.0.0 1367 | integrity: sha256-1rXgTomes9105BjgXqIw0FL6Fz1lqqUTLWOumhWec1M= 1368 | dependencies: 1369 | - control 1370 | - invariant 1371 | - prelude 1372 | type-equality: 1373 | type: registry 1374 | version: 4.0.1 1375 | integrity: sha256-Hs9D6Y71zFi/b+qu5NSbuadUQXe5iv5iWx0226vOHUw= 1376 | dependencies: [] 1377 | typelevel-prelude: 1378 | type: registry 1379 | version: 7.0.0 1380 | integrity: sha256-uFF2ph+vHcQpfPuPf2a3ukJDFmLhApmkpTMviHIWgJM= 1381 | dependencies: 1382 | - prelude 1383 | - type-equality 1384 | unfoldable: 1385 | type: registry 1386 | version: 6.0.0 1387 | integrity: sha256-JtikvJdktRap7vr/K4ITlxUX1QexpnqBq0G/InLr6eg= 1388 | dependencies: 1389 | - foldable-traversable 1390 | - maybe 1391 | - partial 1392 | - prelude 1393 | - tuples 1394 | unicode: 1395 | type: registry 1396 | version: 6.0.0 1397 | integrity: sha256-QJnTVZpmihEAUiMeYrfkusVoziJWp2hJsgi9bMQLue8= 1398 | dependencies: 1399 | - foldable-traversable 1400 | - maybe 1401 | - strings 1402 | unsafe-coerce: 1403 | type: registry 1404 | version: 6.0.0 1405 | integrity: sha256-IqIYW4Vkevn8sI+6aUwRGvd87tVL36BBeOr0cGAE7t0= 1406 | dependencies: [] 1407 | versions: 1408 | type: registry 1409 | version: 7.0.0 1410 | integrity: sha256-+7qxEsCbSl8JDsOsGQO/XxCfcCYak13lJHEXmCzUjIs= 1411 | dependencies: 1412 | - control 1413 | - either 1414 | - foldable-traversable 1415 | - functions 1416 | - integers 1417 | - lists 1418 | - maybe 1419 | - orders 1420 | - parsing 1421 | - partial 1422 | - strings 1423 | web-dom: 1424 | type: registry 1425 | version: 6.0.0 1426 | integrity: sha256-1kSKWFDI4LupdmpjK01b1MMxDFW7jvatEgPgVmCmSBQ= 1427 | dependencies: 1428 | - web-events 1429 | web-events: 1430 | type: registry 1431 | version: 4.0.0 1432 | integrity: sha256-YDt8b6u1tzGtnWyNRodne57iO8FNSGPaTCVzBUyUn4k= 1433 | dependencies: 1434 | - datetime 1435 | - enums 1436 | - foreign 1437 | - nullable 1438 | web-file: 1439 | type: registry 1440 | version: 4.0.0 1441 | integrity: sha256-1h5jPBkvjY71jLEdwVadXCx86/2inNoMBO//Rd3eCSU= 1442 | dependencies: 1443 | - foreign 1444 | - media-types 1445 | - web-dom 1446 | web-html: 1447 | type: registry 1448 | version: 4.1.0 1449 | integrity: sha256-ByqS/h1/yG+hjCOnOQp7L1QpIWzQENNKB1kaHtpEhlE= 1450 | dependencies: 1451 | - js-date 1452 | - web-dom 1453 | - web-file 1454 | - web-storage 1455 | web-storage: 1456 | type: registry 1457 | version: 5.0.0 1458 | integrity: sha256-q+6lxcnfWxus0/nDeFVtF1V+tLehZvvXQ0cduYPLksY= 1459 | dependencies: 1460 | - nullable 1461 | - web-events 1462 | web-xhr: 1463 | type: registry 1464 | version: 5.0.1 1465 | integrity: sha256-3dbIPVG66S+hPrgEVnpD78hrGjE7qlBbsReWOz89Ios= 1466 | dependencies: 1467 | - arraybuffer-types 1468 | - datetime 1469 | - http-methods 1470 | - web-dom 1471 | - web-file 1472 | - web-html 1473 | -------------------------------------------------------------------------------- /spago.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: setup-purescript 3 | dependencies: 4 | - aff 5 | - aff-retry 6 | - affjax 7 | - affjax-node 8 | - argonaut-codecs 9 | - argonaut-core 10 | - arrays 11 | - bifunctors 12 | - control 13 | - effect 14 | - either 15 | - enums 16 | - exceptions 17 | - foldable-traversable 18 | - foreign-object 19 | - github-actions-toolkit 20 | - integers 21 | - lists 22 | - numbers 23 | - maybe 24 | - newtype 25 | - node-buffer 26 | - node-fs 27 | - node-path 28 | - node-process 29 | - ordered-collections 30 | - parsing 31 | - partial 32 | - prelude 33 | - refs 34 | - strings 35 | - tailrec 36 | - transformers 37 | - tuples 38 | - versions 39 | test: 40 | main: Test.Main 41 | dependencies: [] 42 | workspace: 43 | package_set: 44 | registry: 50.4.0 45 | extra_packages: 46 | github-actions-toolkit: 47 | # git: "https://github.com/purescript-contrib/purescript-github-actions-toolkit.git" 48 | git: "https://github.com/srghma/purescript-github-actions-toolkit.git" 49 | ref: "main" 50 | -------------------------------------------------------------------------------- /src/Main.purs: -------------------------------------------------------------------------------- 1 | module Main where 2 | 3 | import Prelude 4 | 5 | import Affjax (printError) 6 | import Affjax.Node as Affjax.Node 7 | import Affjax.ResponseFormat as Affjax.ResponseFormat 8 | import Control.Monad.Except.Trans (ExceptT(..), runExceptT) 9 | import Data.Argonaut.Parser (jsonParser) 10 | import Data.Bifunctor (bimap, lmap) 11 | import Data.Either (Either(..)) 12 | import Data.Foldable (traverse_) 13 | import Data.Maybe (isJust) 14 | import Effect (Effect) 15 | import Effect.Aff (error, launchAff_, runAff_) 16 | import Effect.Class (liftEffect) 17 | import Effect.Exception (message) 18 | import GitHub.Actions.Core as Core 19 | import Node.Encoding (Encoding(..)) 20 | import Node.FS.Aff as FSA 21 | import Node.Process as Process 22 | import Setup.BuildPlan (constructBuildPlan) 23 | import Setup.Data.VersionFiles (V2FileSchema(..), latestVersion) 24 | import Setup.GetTool (getTool) 25 | import Setup.UpdateVersions (updateVersions) 26 | 27 | main :: Effect Unit 28 | main = runAff_ go $ runExceptT do 29 | versionsJson <- getVersionsFile 30 | tools <- constructBuildPlan versionsJson 31 | liftEffect $ Core.info "Constructed build plan." 32 | traverse_ getTool tools 33 | liftEffect $ Core.info "Fetched tools." 34 | where 35 | getVersionsFile = ExceptT do 36 | let V2FileSchema { localFile, fileUrl } = latestVersion 37 | mb <- liftEffect $ Process.lookupEnv "USE_LOCAL_VERSIONS_JSON" 38 | if isJust mb then do 39 | map (lmap error <<< jsonParser) $ FSA.readTextFile UTF8 localFile 40 | else do 41 | map (bimap (error <<< printError) _.body) $ Affjax.Node.get Affjax.ResponseFormat.json fileUrl 42 | 43 | go res = case join res of 44 | Left err -> Core.setFailed (message err) 45 | Right _ -> pure unit 46 | 47 | update :: Effect Unit 48 | update = launchAff_ updateVersions 49 | -------------------------------------------------------------------------------- /src/Setup/BuildPlan.purs: -------------------------------------------------------------------------------- 1 | module Setup.BuildPlan (constructBuildPlan, BuildPlan) where 2 | 3 | import Prelude 4 | 5 | import Control.Monad.Except.Trans (ExceptT, mapExceptT) 6 | import Data.Argonaut.Core (Json) 7 | import Data.Array as Array 8 | import Data.Either (Either(..)) 9 | import Data.Foldable (fold) 10 | import Data.Map as Map 11 | import Data.Maybe (Maybe(..)) 12 | import Data.Traversable (traverse) 13 | import Data.Version (Version) 14 | import Data.Version as Version 15 | import Effect.Aff (Aff, error, throwError) 16 | import Effect.Class (liftEffect) 17 | import Effect.Exception (Error) 18 | import GitHub.Actions.Core as Core 19 | import Setup.Data.Key (Key) 20 | import Setup.Data.Key as Key 21 | import Setup.Data.Tool (Tool) 22 | import Setup.Data.Tool as Tool 23 | import Setup.Data.VersionFiles (V2FileSchema(..), latestVersion, printV2FileError) 24 | import Parsing as Parsing 25 | 26 | -- | The list of tools that should be downloaded and cached by the action 27 | type BuildPlan = Array { tool :: Tool, version :: Version } 28 | 29 | -- | Construct the list of tools that sholud be downloaded and cached by the action 30 | constructBuildPlan :: Json -> ExceptT Error Aff BuildPlan 31 | constructBuildPlan json = map Array.catMaybes $ traverse (resolve json) Tool.allTools 32 | 33 | -- | The parsed value of an input field that specifies a version 34 | data VersionField 35 | -- | Lookup the latest release, pre-release or not 36 | = Unstable 37 | -- | Lookup the latest release that is not a pre-release 38 | | Latest 39 | -- | Use the given version 40 | | Exact Version 41 | 42 | -- | Attempt to read the value of an input specifying a tool version 43 | getVersionField :: Key -> ExceptT Error Aff (Maybe VersionField) 44 | getVersionField key = do 45 | value <- mapExceptT liftEffect $ Core.getInput' (Key.toString key) 46 | case value of 47 | "" -> 48 | pure Nothing 49 | "latest" -> 50 | pure (pure Latest) 51 | "unstable" -> 52 | pure (pure Unstable) 53 | val -> case Version.parseVersion val of 54 | Left msg -> do 55 | liftEffect $ Core.error $ fold [ "Failed to parse version ", val ] 56 | throwError (error (Parsing.parseErrorMessage msg)) 57 | Right version -> 58 | pure (pure (Exact version)) 59 | 60 | -- | Resolve the exact version to provide for a tool in the environment, based 61 | -- | on the action.yml file. 62 | resolve :: Json -> Tool -> ExceptT Error Aff (Maybe { tool :: Tool, version :: Version }) 63 | resolve versionsContents tool = do 64 | let key = Key.fromTool tool 65 | field <- getVersionField key 66 | case field of 67 | Nothing -> pure Nothing 68 | 69 | Just (Exact v) -> liftEffect do 70 | Core.info "Found exact version" 71 | pure (pure { tool, version: v }) 72 | 73 | Just Latest -> liftEffect do 74 | Core.info $ fold [ "Fetching latest stable tag for ", Tool.name tool ] 75 | readVersionFromFile "latest" _.latest 76 | 77 | Just Unstable -> liftEffect do 78 | Core.info $ fold [ "Fetching latest tag (pre-release or not) for ", Tool.name tool ] 79 | readVersionFromFile "unstable" _.unstable 80 | where 81 | readVersionFromFile fieldName fieldSelector = do 82 | let V2FileSchema { decode } = latestVersion 83 | case decode versionsContents of 84 | Left err -> do 85 | Core.setFailed $ fold 86 | [ "Unable to parse version for field '" 87 | , fieldName 88 | , "': " 89 | , printV2FileError err 90 | ] 91 | throwError $ error "Unable to complete fetching version." 92 | 93 | Right toolMap 94 | | Just v <- Map.lookup tool toolMap -> do 95 | pure (pure { tool, version: fieldSelector v }) 96 | | otherwise -> do 97 | Core.setFailed $ fold 98 | [ "Unable to find version for tool '" 99 | , Tool.name tool 100 | , "'. Tools found were: " 101 | , show $ map Tool.name $ Array.fromFoldable $ Map.keys toolMap 102 | ] 103 | throwError $ error "Unable to complete fetching version." 104 | -------------------------------------------------------------------------------- /src/Setup/Data/Key.purs: -------------------------------------------------------------------------------- 1 | module Setup.Data.Key 2 | ( Key 3 | , fromTool 4 | , toString 5 | ) where 6 | 7 | import Setup.Data.Tool (Tool(..)) 8 | 9 | newtype Key = Key String 10 | 11 | purescriptKey :: Key 12 | purescriptKey = Key "purescript" 13 | 14 | spagoKey :: Key 15 | spagoKey = Key "spago" 16 | 17 | psaKey :: Key 18 | psaKey = Key "psa" 19 | 20 | pursTidyKey :: Key 21 | pursTidyKey = Key "purs-tidy" 22 | 23 | zephyrKey :: Key 24 | zephyrKey = Key "zephyr" 25 | 26 | toString :: Key -> String 27 | toString (Key key) = key 28 | 29 | fromTool :: Tool -> Key 30 | fromTool = case _ of 31 | PureScript -> purescriptKey 32 | Spago -> spagoKey 33 | Psa -> psaKey 34 | PursTidy -> pursTidyKey 35 | Zephyr -> zephyrKey 36 | -------------------------------------------------------------------------------- /src/Setup/Data/Platform.purs: -------------------------------------------------------------------------------- 1 | module Setup.Data.Platform where 2 | 3 | import Data.Maybe (Maybe(..)) 4 | import Node.Platform as Platform 5 | import Node.Process as Process 6 | 7 | data Platform = Windows | Mac | Linux 8 | 9 | -- | Parse a platform value from the `process.platform` key 10 | platform :: Platform 11 | platform = case Process.platform of 12 | Just Platform.Win32 -> Windows 13 | Just Platform.Darwin -> Mac 14 | _ -> Linux 15 | -------------------------------------------------------------------------------- /src/Setup/Data/Tool.purs: -------------------------------------------------------------------------------- 1 | module Setup.Data.Tool where 2 | 3 | import Prelude 4 | 5 | import Affjax (URL) 6 | import Data.Bounded.Generic (genericBottom, genericTop) 7 | import Data.Either (fromRight') 8 | import Data.Enum (class Enum, upFromIncluding) 9 | import Data.Enum.Generic (genericPred, genericSucc) 10 | import Data.Foldable (elem, fold) 11 | import Data.Generic.Rep (class Generic) 12 | import Data.Version (Version, parseVersion) 13 | import Data.Version as Version 14 | import Node.Path (FilePath) 15 | import Node.Path as Path 16 | import Partial.Unsafe (unsafeCrashWith) 17 | import Setup.Data.Platform (Platform(..), platform) 18 | 19 | data Tool 20 | = PureScript 21 | | Spago 22 | | Psa 23 | | PursTidy 24 | | Zephyr 25 | 26 | derive instance eqTool :: Eq Tool 27 | derive instance ordTool :: Ord Tool 28 | derive instance genericTool :: Generic Tool _ 29 | 30 | instance boundedTool :: Bounded Tool where 31 | bottom = genericBottom 32 | top = genericTop 33 | 34 | instance enumTool :: Enum Tool where 35 | succ = genericSucc 36 | pred = genericPred 37 | 38 | -- | A list of all available tools in the toolchain 39 | allTools :: Array Tool 40 | allTools = upFromIncluding bottom 41 | 42 | -- | Tools that are required in the toolchain 43 | requiredTools :: Array Tool 44 | requiredTools = [ PureScript, Spago ] 45 | 46 | -- | Tools that are required in the toolchain 47 | required :: Tool -> Boolean 48 | required tool = elem tool requiredTools 49 | 50 | name :: Tool -> String 51 | name = case _ of 52 | PureScript -> "purs" 53 | Spago -> "spago" 54 | Psa -> "psa" 55 | PursTidy -> "purs-tidy" 56 | Zephyr -> "zephyr" 57 | 58 | -- | The source repository for a tool (whether on GitHub or Gitlab) 59 | type ToolRepository = { owner :: String, name :: String } 60 | 61 | repository :: Tool -> ToolRepository 62 | repository = case _ of 63 | PureScript -> 64 | { owner: "purescript", name: "purescript" } 65 | 66 | Spago -> 67 | { owner: "purescript", name: "spago" } 68 | 69 | Psa -> 70 | { owner: "natefaubion", name: "purescript-psa" } 71 | 72 | PursTidy -> 73 | { owner: "natefaubion", name: "purescript-tidy" } 74 | 75 | Zephyr -> 76 | { owner: "coot", name: "zephyr" } 77 | 78 | -- | How a tool will be installed: either a tarball from a URL, or an NPM package 79 | -- | at a particular version. 80 | data InstallMethod = Tarball TarballOpts | NPM NPMPackage 81 | 82 | -- | The source used to download a tarball and its path inside the extracted 83 | -- | directory. 84 | type TarballOpts = 85 | { source :: URL 86 | , getExecutablePath :: FilePath -> FilePath 87 | } 88 | 89 | -- | An NPM package. Example: "purescript-psa@0.7.2" 90 | type NPMPackage = String 91 | 92 | -- | The installation method for a tool, which includes the source path necessary 93 | -- | to download or install the tool. 94 | installMethod :: Tool -> Version -> InstallMethod 95 | installMethod tool version = do 96 | let 97 | toolName = name tool 98 | toolRepo = repository tool 99 | formatArgs = { repo: toolRepo, tag: formatTag, tarball: _ } 100 | 101 | formatGitHub' = formatGitHub <<< formatArgs 102 | 103 | unsafeVersion str = fromRight' (\_ -> unsafeCrashWith "Unexpected Left") $ parseVersion str 104 | 105 | executableName = case platform of 106 | Windows -> toolName <> ".exe" 107 | _ -> toolName 108 | 109 | case tool of 110 | PureScript -> Tarball 111 | { source: formatGitHub' case platform of 112 | Windows -> "win64" 113 | Mac -> "macos" 114 | Linux -> "linux64" 115 | , getExecutablePath: \p -> Path.concat [ p, "purescript", executableName ] 116 | } 117 | 118 | Spago -> 119 | if version >= unsafeVersion "0.90.0" then NPM ("spago@" <> Version.showVersion version) 120 | else Tarball 121 | { source: formatGitHub' 122 | -- Spago has changed naming conventions from version to version 123 | if version >= unsafeVersion "0.18.1" then case platform of 124 | Windows -> "Windows" 125 | Mac -> "macOS" 126 | Linux -> "Linux" 127 | else if version == unsafeVersion "0.18.0" then case platform of 128 | Windows -> "windows-latest" 129 | Mac -> "macOS-latest" 130 | Linux -> "linux-latest" 131 | else case platform of 132 | Windows -> "windows" 133 | Mac -> "osx" 134 | Linux -> "linux" 135 | , getExecutablePath: \p -> Path.concat [ p, executableName ] 136 | } 137 | 138 | Psa -> 139 | NPM ("purescript-psa@" <> Version.showVersion version) 140 | 141 | PursTidy -> 142 | NPM ("purs-tidy@" <> Version.showVersion version) 143 | 144 | Zephyr -> Tarball 145 | { source: formatGitHub' $ case platform of 146 | Windows -> "Windows" 147 | Mac -> "macOS" 148 | Linux -> "Linux" 149 | , getExecutablePath: \p -> Path.concat [ p, "zephyr", executableName ] 150 | } 151 | where 152 | -- Format the release tag for a tool at a specific version. Not all tools use 153 | -- the same format. 154 | -- 155 | -- Example: "v0.13.2", "0.15.2" 156 | formatTag :: String 157 | formatTag = do 158 | let versionStr = Version.showVersion version 159 | if tool `elem` [ PureScript, Zephyr, Psa ] then 160 | fold [ "v", versionStr ] 161 | else 162 | versionStr 163 | 164 | formatGitHub :: { repo :: ToolRepository, tag :: String, tarball :: String } -> String 165 | formatGitHub { repo, tag, tarball } = 166 | -- Example: https://github.com/purescript/purescript/releases/download/v0.13.8/win64.tar.gz 167 | fold 168 | [ "https://github.com/" 169 | , repo.owner 170 | , "/" 171 | , repo.name 172 | , "/releases/download/" 173 | , tag 174 | , "/" 175 | , tarball 176 | , ".tar.gz" 177 | ] 178 | -------------------------------------------------------------------------------- /src/Setup/Data/VersionFiles.purs: -------------------------------------------------------------------------------- 1 | module Setup.Data.VersionFiles where 2 | 3 | import Prelude 4 | 5 | import Data.Argonaut.Core (Json, jsonEmptyObject) 6 | import Data.Argonaut.Decode (JsonDecodeError(..), decodeJson, printJsonDecodeError) 7 | import Data.Argonaut.Encode (encodeJson, (:=), (~>)) 8 | import Data.Array (fold) 9 | import Data.Bifunctor (lmap) 10 | import Data.Either (Either(..)) 11 | import Data.FoldableWithIndex (foldlWithIndex) 12 | import Data.Map (Map) 13 | import Data.Map as Map 14 | import Data.Maybe (Maybe(..)) 15 | import Data.Newtype (class Newtype) 16 | import Data.TraversableWithIndex (forWithIndex) 17 | import Data.Tuple (Tuple(..)) 18 | import Data.Version (Version) 19 | import Data.Version as Version 20 | import Foreign.Object (Object) 21 | import Setup.Data.Tool (Tool(..)) 22 | import Parsing (ParseError) 23 | 24 | latestVersion :: V2FileSchema 25 | latestVersion = version2 26 | 27 | data V2FileError 28 | = JsonCodecError JsonDecodeError 29 | | VersionParseError String ParseError 30 | | ToolNameError JsonDecodeError 31 | 32 | printV2FileError :: V2FileError -> String 33 | printV2FileError = case _ of 34 | JsonCodecError e -> printJsonDecodeError e 35 | VersionParseError field e -> fold 36 | [ "Version parse failure for key, " 37 | , field 38 | , "': " 39 | , show e 40 | ] 41 | ToolNameError e -> fold 42 | [ "Unable to convert String into Tool. " 43 | , printJsonDecodeError e 44 | ] 45 | 46 | type LatestUnstable a = 47 | { latest :: a 48 | , unstable :: a 49 | } 50 | 51 | newtype V2FileSchema = V2FileSchema 52 | { fileUrl :: String 53 | , localFile :: String 54 | , encode :: Map Tool (LatestUnstable Version) -> Json 55 | , decode :: Json -> Either V2FileError (Map Tool (LatestUnstable Version)) 56 | } 57 | 58 | derive instance Newtype V2FileSchema _ 59 | 60 | version2 :: V2FileSchema 61 | version2 = V2FileSchema 62 | { fileUrl: "https://raw.githubusercontent.com/purescript-contrib/setup-purescript/main" <> filePath 63 | , localFile: "." <> filePath 64 | , encode: foldlWithIndex encodeFoldFn jsonEmptyObject 65 | , decode: \j -> do 66 | obj :: Object Json <- lmap JsonCodecError $ decodeJson j 67 | keyVals <- forWithIndex obj \key val -> do 68 | tool <- strToTool key 69 | { latest 70 | , unstable 71 | } :: LatestUnstable String <- lmap JsonCodecError $ decodeJson val 72 | latest' <- lmap (VersionParseError (key <> ".latest")) $ Version.parseVersion latest 73 | unstable' <- lmap (VersionParseError (key <> ".unstable")) $ Version.parseVersion unstable 74 | pure $ Tuple tool { latest: latest', unstable: unstable' } 75 | pure $ Map.fromFoldable keyVals 76 | } 77 | where 78 | filePath = "/dist/versions-v2.json" 79 | encodeFoldFn tool acc { latest, unstable } 80 | | Just toolStr <- toolToMbString tool = do 81 | let rec = { latest: Version.showVersion latest, unstable: Version.showVersion unstable } 82 | toolStr := rec ~> acc 83 | | otherwise = 84 | acc 85 | 86 | -- in case we add support for other tools in the future... 87 | toolToMbString = case _ of 88 | PureScript -> Just "purs" 89 | Spago -> Just "spago" 90 | Psa -> Just "psa" 91 | PursTidy -> Just "purs-tidy" 92 | Zephyr -> Just "zephyr" 93 | 94 | strToTool = case _ of 95 | "purs" -> Right PureScript 96 | "spago" -> Right Spago 97 | "psa" -> Right Psa 98 | "purs-tidy" -> Right PursTidy 99 | "zephyr" -> Right Zephyr 100 | str -> Left $ ToolNameError $ UnexpectedValue $ encodeJson str 101 | 102 | newtype V1FileSchema = V1FileSchema 103 | { localFile :: String 104 | , encode :: Map Tool Version -> Json 105 | } 106 | 107 | derive instance Newtype V1FileSchema _ 108 | 109 | version1 :: V1FileSchema 110 | version1 = V1FileSchema 111 | { localFile: "./dist/versions.json" 112 | , encode: foldlWithIndex encodeFoldFn jsonEmptyObject 113 | } 114 | where 115 | encodeFoldFn tool acc version 116 | | Just toolStr <- printTool tool = 117 | toolStr := Version.showVersion version ~> acc 118 | | otherwise = 119 | acc 120 | 121 | -- We preserve the set of tools that existed at the time this version format was produced; 122 | -- if more tools are added, they should map to `Nothing` 123 | printTool = case _ of 124 | PureScript -> Just "purs" 125 | Spago -> Just "spago" 126 | Psa -> Just "psa" 127 | PursTidy -> Just "purs-tidy" 128 | Zephyr -> Just "zephyr" 129 | -------------------------------------------------------------------------------- /src/Setup/GetTool.purs: -------------------------------------------------------------------------------- 1 | module Setup.GetTool (getTool) where 2 | 3 | import Prelude 4 | 5 | import Control.Monad.Except.Trans (ExceptT, mapExceptT) 6 | import Data.Foldable (fold) 7 | import Data.Maybe (Maybe(..)) 8 | import Data.Version (Version) 9 | import Data.Version as Version 10 | import Effect.Aff (Aff) 11 | import Effect.Class (liftEffect) 12 | import Effect.Exception (Error) 13 | import GitHub.Actions.Core as Core 14 | import GitHub.Actions.Exec as Exec 15 | import GitHub.Actions.ToolCache as ToolCache 16 | import Setup.Data.Platform (Platform(..), platform) 17 | import Setup.Data.Tool (InstallMethod(..), Tool) 18 | import Setup.Data.Tool as Tool 19 | 20 | getTool :: { tool :: Tool, version :: Version } -> ExceptT Error Aff Unit 21 | getTool { tool, version } = do 22 | let 23 | name = Tool.name tool 24 | installMethod = Tool.installMethod tool version 25 | 26 | liftEffect $ Core.info $ fold [ "Fetching ", name ] 27 | 28 | case installMethod of 29 | Tarball opts -> do 30 | mbPath <- mapExceptT liftEffect $ ToolCache.find { arch: Nothing, toolName: name, versionSpec: Version.showVersion version } 31 | case mbPath of 32 | Just path -> liftEffect do 33 | Core.info $ fold [ "Found cached version of ", name ] 34 | Core.addPath path 35 | 36 | Nothing -> do 37 | downloadPath <- ToolCache.downloadTool' opts.source 38 | extractedPath <- ToolCache.extractTar' downloadPath 39 | cached <- ToolCache.cacheFile { sourceFile: opts.getExecutablePath extractedPath, tool: name, version: Version.showVersion version, targetFile: name, arch: Nothing } 40 | 41 | liftEffect do 42 | Core.info $ fold [ "Cached path ", cached, ", adding to PATH" ] 43 | Core.addPath cached 44 | 45 | NPM package -> void $ case platform of 46 | Windows -> 47 | Exec.exec { command: "npm", args: Just [ "install", "-g", package ], options: Nothing } 48 | _ -> 49 | Exec.exec { command: "sudo npm", args: Just [ "install", "-g", package ], options: Nothing } 50 | -------------------------------------------------------------------------------- /src/Setup/UpdateVersions.purs: -------------------------------------------------------------------------------- 1 | -- | The source used to fetch and update the latest versions in the versions.json 2 | -- | file, which records the latest version of each tool. 3 | module Setup.UpdateVersions (updateVersions) where 4 | 5 | import Prelude 6 | 7 | import Affjax.Node as Affjax.Node 8 | import Affjax.ResponseFormat as Affjax.ResponseFormat 9 | import Control.Alt ((<|>)) 10 | import Control.Monad.Rec.Class (class MonadRec, Step(..), tailRecM) 11 | import Data.Argonaut.Core (Json, stringifyWithIndent) 12 | import Data.Argonaut.Decode (decodeJson, printJsonDecodeError, (.:)) 13 | import Data.Array as Array 14 | import Data.Either (Either(..), hush) 15 | import Data.Foldable (fold, maximum) 16 | import Data.Int (toNumber) 17 | import Data.List as List 18 | import Data.Map as Map 19 | import Data.Maybe (Maybe(..), fromMaybe) 20 | import Data.String as String 21 | import Data.Traversable (for, traverse) 22 | import Data.Tuple (Tuple(..)) 23 | import Data.Version (Version) 24 | import Data.Version as Version 25 | import Effect (Effect) 26 | import Effect.Aff (Aff, Error, Milliseconds(..), delay, error, throwError) 27 | import Effect.Aff.Retry (RetryPolicy, RetryPolicyM, RetryStatus(..)) 28 | import Effect.Aff.Retry as Retry 29 | import Effect.Class (liftEffect) 30 | import Effect.Ref as Ref 31 | import GitHub.Actions.Core (warning) 32 | import Data.Number (pow) 33 | import Node.Encoding (Encoding(..)) 34 | import Node.FS.Sync (writeTextFile) 35 | import Node.Path (FilePath) 36 | import Setup.Data.Tool (Tool(..)) 37 | import Setup.Data.Tool as Tool 38 | import Setup.Data.VersionFiles (V1FileSchema(..), V2FileSchema(..), version1, version2) 39 | import Parsing (ParseError) 40 | 41 | -- | Write the latest version of each supported tool 42 | updateVersions :: Aff Unit 43 | updateVersions = do 44 | versions <- for Tool.allTools \tool -> do 45 | delay (Milliseconds 500.0) 46 | versionRec <- fetchLatestReleaseVersion tool 47 | pure $ Tuple tool versionRec 48 | 49 | updateV1File versions 50 | updateV2File versions 51 | where 52 | updateV1File versions = liftEffect do 53 | let V1FileSchema { localFile, encode } = version1 54 | writeVersionsFile localFile 55 | $ encode 56 | $ Map.fromFoldable 57 | $ map (map _.latest) versions 58 | 59 | updateV2File versions = liftEffect do 60 | let V2FileSchema { localFile, encode } = version2 61 | writeVersionsFile localFile 62 | $ encode 63 | $ Map.fromFoldable versions 64 | 65 | writeVersionsFile :: FilePath -> Json -> Effect Unit 66 | writeVersionsFile path = writeTextFile UTF8 path <<< (_ <> "\n") <<< stringifyWithIndent 2 67 | 68 | -- | Find the latest release version for a given tool. Prefers explicit releases 69 | -- | as listed in GitHub releases, but for tools which don't support GitHub 70 | -- | releases, falls back to the highest valid semantic version tag for the tool. 71 | fetchLatestReleaseVersion :: Tool -> Aff { latest :: Version, unstable :: Version } 72 | fetchLatestReleaseVersion tool = case tool of 73 | PureScript -> fetchFromGitHubReleases toolRepository 74 | Spago -> fetchFromNpmReleases toolRepository.name 75 | Psa -> fetchFromGitHubTags toolRepository 76 | PursTidy -> fetchFromGitHubTags toolRepository 77 | Zephyr -> fetchFromGitHubReleases toolRepository 78 | where 79 | toolRepository = Tool.repository tool 80 | 81 | type NpmOutput = { "dist-tags" :: { latest :: String, next :: String } } 82 | 83 | -- See all versions - https://www.npmjs.com/package/spago?activeTab=versions 84 | fetchFromNpmReleases :: String -> Aff { latest :: Version, unstable :: Version } 85 | fetchFromNpmReleases packageName = recover do 86 | let url = "https://registry.npmjs.org/" <> packageName 87 | Affjax.Node.get Affjax.ResponseFormat.json url >>= case _ of 88 | Left err -> throwError (error $ Affjax.Node.printError err) 89 | Right { body } -> case decodeJson body of 90 | Left e -> do 91 | throwError $ error 92 | $ fold 93 | [ "Failed to decode Npm response. This is most likely due to a timeout.\n\n" 94 | , printJsonDecodeError e 95 | , stringifyWithIndent 2 body 96 | ] 97 | Right (npmOutput :: NpmOutput) -> do 98 | unstable <- strToVersionOrError npmOutput."dist-tags".next -- for example 0.93.x 99 | latest <- strToVersionOrError npmOutput."dist-tags".latest -- for example 0.21.0 100 | pure { latest, unstable } 101 | 102 | where 103 | strToVersionOrError :: String -> Aff Version 104 | strToVersionOrError tagName = 105 | case tagStrToVersion tagName of 106 | Left _ -> 107 | throwError $ error $ fold 108 | [ "Got invalid version" 109 | , tagName 110 | , " from " 111 | , packageName 112 | ] 113 | Right version -> pure version 114 | 115 | -- TODO: These functions really ought to be in ExceptT to avoid all the 116 | -- nested branches. 117 | fetchFromGitHubReleases :: Tool.ToolRepository -> Aff { latest :: Version, unstable :: Version } 118 | fetchFromGitHubReleases repo = recover do 119 | page <- liftEffect (Ref.new 1) 120 | untilBothVersionsFound \firstUnstableVersion -> do 121 | versions <- liftEffect (Ref.read page) >>= toolVersions repo 122 | case versions of 123 | Just versions' -> do 124 | let 125 | unstable = firstUnstableVersion <|> Array.head versions' 126 | latest = versions' # Array.find \v -> 127 | (not $ Version.isPreRelease v) && (List.null $ Version.buildMetadata v) 128 | case latest of 129 | Nothing -> do 130 | liftEffect $ void $ Ref.modify (_ + 1) page 131 | pure $ Left unstable 132 | Just v -> do 133 | pure $ Right 134 | { latest: v 135 | , unstable: fromMaybe v unstable 136 | } 137 | 138 | Nothing -> 139 | case firstUnstableVersion of 140 | Nothing -> 141 | throwError $ error "Could not find a pre-release or stable version" 142 | Just _ -> 143 | throwError $ error "Could not find version that is not a pre-release version" 144 | where 145 | -- based on `untilJust` 146 | untilBothVersionsFound :: forall a b m. MonadRec m => (Maybe a -> m (Either (Maybe a) b)) -> m b 147 | untilBothVersionsFound f = Nothing # tailRecM \mb1 -> f mb1 <#> case _ of 148 | Left mb2 -> Loop mb2 149 | Right x -> Done x 150 | 151 | toolVersions :: Tool.ToolRepository -> Int -> Aff (Maybe (Array Version)) 152 | toolVersions repo page = do 153 | let 154 | url = 155 | "https://api.github.com/repos/" 156 | <> repo.owner 157 | <> "/" 158 | <> repo.name 159 | <> "/releases?per_page=10&page=" 160 | <> show page 161 | 162 | Affjax.Node.get Affjax.ResponseFormat.json url >>= case _ of 163 | Left err -> throwError (error $ Affjax.Node.printError err) 164 | Right { body } -> case decodeJson body of 165 | Left e -> do 166 | throwError $ error 167 | $ fold 168 | [ "Failed to decode GitHub response. This is most likely due to a timeout.\n\n" 169 | , printJsonDecodeError e 170 | , stringifyWithIndent 2 body 171 | ] 172 | Right [] -> pure Nothing 173 | Right objects -> 174 | Just 175 | <$> Array.catMaybes 176 | <$> for objects \obj -> 177 | case obj .: "tag_name" of 178 | Left e -> 179 | throwError $ error $ fold 180 | [ "Failed to get tag from GitHub response: " 181 | , printJsonDecodeError e 182 | ] 183 | Right tagName -> 184 | case tagStrToVersion tagName of 185 | Left _ -> do 186 | liftEffect $ warning $ fold 187 | [ "Got invalid version" 188 | , tagName 189 | , " from " 190 | , repo.name 191 | ] 192 | pure Nothing 193 | Right version -> case obj .: "draft" of 194 | Left e -> 195 | throwError $ error $ fold 196 | [ "Failed to get draft from GitHub response: " 197 | , printJsonDecodeError e 198 | ] 199 | Right isDraft -> 200 | pure 201 | if isDraft then Nothing 202 | else Just version 203 | 204 | tagStrToVersion :: String -> Either ParseError Version 205 | tagStrToVersion tagStr = 206 | tagStr 207 | # String.stripPrefix (String.Pattern "v") 208 | # fromMaybe tagStr 209 | # Version.parseVersion 210 | 211 | -- If a tool doesn't use GitHub releases and instead only tags versions, then 212 | -- we have to fetch the tags, parse them as appropriate versions, and then sort 213 | -- them according to their semantic version to get the latest one. 214 | fetchFromGitHubTags :: Tool.ToolRepository -> Aff { latest :: Version, unstable :: Version } 215 | fetchFromGitHubTags repo = recover do 216 | let url = "https://api.github.com/repos/" <> repo.owner <> "/" <> repo.name <> "/tags" 217 | 218 | Affjax.Node.get Affjax.ResponseFormat.json url >>= case _ of 219 | Left err -> do 220 | throwError (error $ Affjax.Node.printError err) 221 | 222 | Right { body } -> case traverse (_ .: "name") =<< decodeJson body of 223 | Left e -> do 224 | throwError $ error $ fold 225 | [ "Failed to decode GitHub response. This is most likely due to a timeout.\n\n" 226 | , printJsonDecodeError e 227 | , stringifyWithIndent 2 body 228 | ] 229 | 230 | Right arr -> do 231 | let 232 | tags = Array.mapMaybe (tagStrToVersion >>> hush) arr 233 | 234 | case maximum tags of 235 | Nothing -> 236 | throwError $ error "Could not download latest release version." 237 | 238 | Just v -> 239 | pure { latest: v, unstable: v } 240 | 241 | -- Attempt to recover from a failed request by re-attempting according to an 242 | -- exponential backoff strategy. 243 | recover :: Aff ~> Aff 244 | recover action = Retry.recovering policy checks \_ -> action 245 | where 246 | policy :: RetryPolicyM Aff 247 | policy = exponentialBackoff (Milliseconds 5000.0) <> Retry.limitRetries 4 248 | 249 | checks :: Array (RetryStatus -> Error -> Aff Boolean) 250 | checks = [ \_ -> \_ -> pure true ] 251 | 252 | exponentialBackoff :: Milliseconds -> RetryPolicy 253 | exponentialBackoff (Milliseconds base) = 254 | Retry.retryPolicy 255 | \(RetryStatus { iterNumber: n }) -> 256 | Just $ Milliseconds $ base * pow 3.0 (toNumber n) 257 | -------------------------------------------------------------------------------- /update.js: -------------------------------------------------------------------------------- 1 | import { update } from './output/index.js' 2 | 3 | update(); 4 | --------------------------------------------------------------------------------