├── .github └── workflows │ ├── check-dist.yml │ └── validate.yml ├── .gitignore ├── .prettierrc.json ├── LICENSE ├── README.md ├── action.yml ├── check-version.sh ├── dist └── index.js ├── package-lock.json ├── package.json ├── src ├── binaryen │ ├── install.ts │ └── sys.ts ├── index.ts ├── tinygo │ ├── install.ts │ └── sys.ts └── utils.ts ├── test-binaryen.sh ├── test-build.sh ├── test └── test.go └── tsconfig.json /.github/workflows/check-dist.yml: -------------------------------------------------------------------------------- 1 | name: Check dist/ 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths-ignore: 8 | - '**.md' 9 | pull_request: 10 | paths-ignore: 11 | - '**.md' 12 | workflow_dispatch: 13 | 14 | jobs: 15 | check-dist: 16 | runs-on: ubuntu-latest 17 | 18 | steps: 19 | - uses: actions/checkout@v4 20 | 21 | - name: Set Node.js 20.x 22 | uses: actions/setup-node@v3 23 | with: 24 | node-version: 20.x 25 | 26 | - name: Install dependencies 27 | run: npm ci 28 | 29 | - name: Rebuild the dist/ directory 30 | run: npm run build 31 | 32 | - name: Compare the expected and actual dist/ directories 33 | run: | 34 | if [ "$(git diff --ignore-space-at-eol dist/ | wc -l)" -gt "0" ]; then 35 | echo "Detected uncommitted changes after build. See status below:" 36 | git diff 37 | exit 1 38 | fi 39 | id: diff 40 | 41 | # If index.js was different than expected, upload the expected version as an artifact 42 | - uses: actions/upload-artifact@v3 43 | if: ${{ failure() && steps.diff.conclusion == 'failure' }} 44 | with: 45 | name: dist 46 | path: dist/ 47 | -------------------------------------------------------------------------------- /.github/workflows/validate.yml: -------------------------------------------------------------------------------- 1 | name: Validate 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | 8 | jobs: 9 | verify: 10 | name: Verify setup 11 | runs-on: ${{ matrix.os }} 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | os: [macos-latest, windows-latest, ubuntu-latest] 16 | tinygo: ['0.33.0', '0.34.0', '0.35.0'] 17 | steps: 18 | - uses: actions/checkout@v4 19 | - uses: actions/setup-go@v4 20 | with: 21 | go-version: '1.23' 22 | 23 | - name: setup-tinygo ${{ matrix.tinygo }} 24 | uses: ./ 25 | with: 26 | tinygo-version: ${{ matrix.tinygo }} 27 | binaryen-version: '121' 28 | 29 | - name: Verify version 30 | run: ./check-version.sh ${{ matrix.tinygo }} 31 | shell: bash 32 | 33 | - name: Test build 34 | run: ./test-build.sh 35 | shell: bash 36 | 37 | no-binaryen: 38 | name: No Binaryen 39 | # using macos because ubuntu has binaryen pre-installed 40 | # TO-DO: implement a stable testing method 41 | runs-on: macos-latest 42 | steps: 43 | - uses: actions/checkout@v4 44 | - uses: actions/setup-go@v4 45 | with: 46 | go-version: '1.23' 47 | 48 | - name: setup-tinygo 49 | uses: ./ 50 | with: 51 | tinygo-version: '0.35.0' 52 | install-binaryen: 'false' 53 | 54 | - name: Binaryen not installed 55 | run: ./test-binaryen.sh 56 | shell: bash 57 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib 3 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "tabWidth": 2, 4 | "trailingComma": "all" 5 | } 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Alessandro Cifani 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-tinygo 2 | 3 | [![Check dist/](https://github.com/acifani/setup-tinygo/actions/workflows/check-dist.yml/badge.svg)](https://github.com/acifani/setup-tinygo/actions/workflows/check-dist.yml) 4 | [![Validate](https://github.com/acifani/setup-tinygo/actions/workflows/validate.yml/badge.svg)](https://github.com/acifani/setup-tinygo/actions/workflows/validate.yml) 5 | 6 | This actions sets up a TinyGo environment for GitHub Actions. 7 | 8 | ## Usage 9 | 10 | ### Basic 11 | 12 | ```yaml 13 | steps: 14 | - uses: actions/checkout@v2 15 | - uses: acifani/setup-tinygo@v2 16 | with: 17 | tinygo-version: '0.30.0' 18 | ``` 19 | 20 | ### With matrix expansion 21 | 22 | ```yaml 23 | jobs: 24 | build: 25 | runs-on: ubuntu-latest 26 | strategy: 27 | matrix: 28 | tinygo: ['0.29.0', '0.30.0'] 29 | name: TinyGo ${{ matrix.tinygo }} 30 | steps: 31 | - uses: actions/checkout@v2 32 | - uses: acifani/setup-tinygo@v2 33 | with: 34 | tinygo-version: ${{ matrix.tinygo }} 35 | ``` 36 | 37 | ### With custom Go version 38 | 39 | TinyGo needs Go and, by default, this action will use whatever 40 | version is available in the runner. If you want to control the 41 | Go version, you can use `actions/setup-go` before `acifani/setup-tinygo` 42 | 43 | ```yaml 44 | steps: 45 | - uses: actions/checkout@v2 46 | - uses: actions/setup-go@v2 47 | with: 48 | go-version: 1.21 49 | - uses: acifani/setup-tinygo@v2 50 | with: 51 | tinygo-version: '0.30.0' 52 | ``` 53 | 54 | ### With custom Binaryen version 55 | 56 | This action will install [Binaryen](https://github.com/WebAssembly/binaryen) 57 | which is needed for building WASM on Windows and MacOS. 58 | You can customize the version with the dedicated input value 59 | 60 | ```yaml 61 | steps: 62 | - uses: actions/checkout@v2 63 | - uses: acifani/setup-tinygo@v2 64 | with: 65 | tinygo-version: '0.30.0' 66 | binaryen-version: '116' 67 | ``` 68 | 69 | ### Without Binaryen 70 | 71 | If you don't need Binaryen, you can omit the installation 72 | 73 | ```yaml 74 | steps: 75 | - uses: actions/checkout@v2 76 | - uses: acifani/setup-tinygo@v2 77 | with: 78 | tinygo-version: '0.30.0' 79 | install-binaryen: 'false' 80 | ``` 81 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: 'Setup TinyGo' 2 | description: 'Set up a specific version of TinyGo and add it to the PATH' 3 | author: acifani 4 | branding: 5 | icon: 'play' 6 | color: 'blue' 7 | inputs: 8 | tinygo-version: 9 | description: 'The exact TinyGo version to download and use.' 10 | default: '0.30.0' 11 | install-binaryen: 12 | description: 'Whether you want to install Binaryen or not.' 13 | default: 'true' 14 | binaryen-version: 15 | description: 'The exact Binaryen version to download and use.' 16 | default: '116' 17 | runs: 18 | using: 'node20' 19 | main: 'dist/index.js' 20 | -------------------------------------------------------------------------------- /check-version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ -z "$1" ]; then 4 | echo "Must supply tinygo version argument" 5 | exit 1 6 | fi 7 | 8 | tinygo_version="$(tinygo version)" 9 | echo "Found tinygo version '$tinygo_version'" 10 | if [ -z "$(echo $tinygo_version | grep $1)" ]; then 11 | echo "Unexpected version" 12 | exit 1 13 | fi 14 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "setup-tinygo", 3 | "version": "1.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "setup-tinygo", 9 | "version": "1.0.0", 10 | "license": "MIT", 11 | "dependencies": { 12 | "@actions/core": "^1.10.1", 13 | "@actions/tool-cache": "^2.0.1" 14 | }, 15 | "devDependencies": { 16 | "@tsconfig/node20": "^20.1.2", 17 | "@types/node": "^20.8.9", 18 | "@vercel/ncc": "^0.38.1", 19 | "prettier": "^3.0.3", 20 | "typescript": "^5.2.2" 21 | } 22 | }, 23 | "node_modules/@actions/core": { 24 | "version": "1.10.1", 25 | "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.1.tgz", 26 | "integrity": "sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==", 27 | "dependencies": { 28 | "@actions/http-client": "^2.0.1", 29 | "uuid": "^8.3.2" 30 | } 31 | }, 32 | "node_modules/@actions/core/node_modules/uuid": { 33 | "version": "8.3.2", 34 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", 35 | "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", 36 | "bin": { 37 | "uuid": "dist/bin/uuid" 38 | } 39 | }, 40 | "node_modules/@actions/exec": { 41 | "version": "1.1.0", 42 | "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.0.tgz", 43 | "integrity": "sha512-LImpN9AY0J1R1mEYJjVJfSZWU4zYOlEcwSTgPve1rFQqK5AwrEs6uWW5Rv70gbDIQIAUwI86z6B+9mPK4w9Sbg==", 44 | "dependencies": { 45 | "@actions/io": "^1.0.1" 46 | } 47 | }, 48 | "node_modules/@actions/http-client": { 49 | "version": "2.1.0", 50 | "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.1.0.tgz", 51 | "integrity": "sha512-BonhODnXr3amchh4qkmjPMUO8mFi/zLaaCeCAJZqch8iQqyDnVIkySjB38VHAC8IJ+bnlgfOqlhpyCUZHlQsqw==", 52 | "dependencies": { 53 | "tunnel": "^0.0.6" 54 | } 55 | }, 56 | "node_modules/@actions/io": { 57 | "version": "1.1.1", 58 | "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.1.tgz", 59 | "integrity": "sha512-Qi4JoKXjmE0O67wAOH6y0n26QXhMKMFo7GD/4IXNVcrtLjUlGjGuVys6pQgwF3ArfGTQu0XpqaNr0YhED2RaRA==" 60 | }, 61 | "node_modules/@actions/tool-cache": { 62 | "version": "2.0.1", 63 | "resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-2.0.1.tgz", 64 | "integrity": "sha512-iPU+mNwrbA8jodY8eyo/0S/QqCKDajiR8OxWTnSk/SnYg0sj8Hp4QcUEVC1YFpHWXtrfbQrE13Jz4k4HXJQKcA==", 65 | "dependencies": { 66 | "@actions/core": "^1.2.6", 67 | "@actions/exec": "^1.0.0", 68 | "@actions/http-client": "^2.0.1", 69 | "@actions/io": "^1.1.1", 70 | "semver": "^6.1.0", 71 | "uuid": "^3.3.2" 72 | } 73 | }, 74 | "node_modules/@tsconfig/node20": { 75 | "version": "20.1.2", 76 | "resolved": "https://registry.npmjs.org/@tsconfig/node20/-/node20-20.1.2.tgz", 77 | "integrity": "sha512-madaWq2k+LYMEhmcp0fs+OGaLFk0OenpHa4gmI4VEmCKX4PJntQ6fnnGADVFrVkBj0wIdAlQnK/MrlYTHsa1gQ==", 78 | "dev": true 79 | }, 80 | "node_modules/@types/node": { 81 | "version": "20.8.9", 82 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", 83 | "integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==", 84 | "dev": true, 85 | "dependencies": { 86 | "undici-types": "~5.26.4" 87 | } 88 | }, 89 | "node_modules/@vercel/ncc": { 90 | "version": "0.38.1", 91 | "resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.38.1.tgz", 92 | "integrity": "sha512-IBBb+iI2NLu4VQn3Vwldyi2QwaXt5+hTyh58ggAMoCGE6DJmPvwL3KPBWcJl1m9LYPChBLE980Jw+CS4Wokqxw==", 93 | "dev": true, 94 | "bin": { 95 | "ncc": "dist/ncc/cli.js" 96 | } 97 | }, 98 | "node_modules/prettier": { 99 | "version": "3.0.3", 100 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", 101 | "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", 102 | "dev": true, 103 | "bin": { 104 | "prettier": "bin/prettier.cjs" 105 | }, 106 | "engines": { 107 | "node": ">=14" 108 | }, 109 | "funding": { 110 | "url": "https://github.com/prettier/prettier?sponsor=1" 111 | } 112 | }, 113 | "node_modules/semver": { 114 | "version": "6.3.1", 115 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", 116 | "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", 117 | "bin": { 118 | "semver": "bin/semver.js" 119 | } 120 | }, 121 | "node_modules/tunnel": { 122 | "version": "0.0.6", 123 | "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", 124 | "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", 125 | "engines": { 126 | "node": ">=0.6.11 <=0.7.0 || >=0.7.3" 127 | } 128 | }, 129 | "node_modules/typescript": { 130 | "version": "5.2.2", 131 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", 132 | "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", 133 | "dev": true, 134 | "bin": { 135 | "tsc": "bin/tsc", 136 | "tsserver": "bin/tsserver" 137 | }, 138 | "engines": { 139 | "node": ">=14.17" 140 | } 141 | }, 142 | "node_modules/undici-types": { 143 | "version": "5.26.5", 144 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", 145 | "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", 146 | "dev": true 147 | }, 148 | "node_modules/uuid": { 149 | "version": "3.4.0", 150 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", 151 | "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", 152 | "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.", 153 | "bin": { 154 | "uuid": "bin/uuid" 155 | } 156 | } 157 | }, 158 | "dependencies": { 159 | "@actions/core": { 160 | "version": "1.10.1", 161 | "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.1.tgz", 162 | "integrity": "sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==", 163 | "requires": { 164 | "@actions/http-client": "^2.0.1", 165 | "uuid": "^8.3.2" 166 | }, 167 | "dependencies": { 168 | "uuid": { 169 | "version": "8.3.2", 170 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", 171 | "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" 172 | } 173 | } 174 | }, 175 | "@actions/exec": { 176 | "version": "1.1.0", 177 | "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.0.tgz", 178 | "integrity": "sha512-LImpN9AY0J1R1mEYJjVJfSZWU4zYOlEcwSTgPve1rFQqK5AwrEs6uWW5Rv70gbDIQIAUwI86z6B+9mPK4w9Sbg==", 179 | "requires": { 180 | "@actions/io": "^1.0.1" 181 | } 182 | }, 183 | "@actions/http-client": { 184 | "version": "2.1.0", 185 | "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.1.0.tgz", 186 | "integrity": "sha512-BonhODnXr3amchh4qkmjPMUO8mFi/zLaaCeCAJZqch8iQqyDnVIkySjB38VHAC8IJ+bnlgfOqlhpyCUZHlQsqw==", 187 | "requires": { 188 | "tunnel": "^0.0.6" 189 | } 190 | }, 191 | "@actions/io": { 192 | "version": "1.1.1", 193 | "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.1.tgz", 194 | "integrity": "sha512-Qi4JoKXjmE0O67wAOH6y0n26QXhMKMFo7GD/4IXNVcrtLjUlGjGuVys6pQgwF3ArfGTQu0XpqaNr0YhED2RaRA==" 195 | }, 196 | "@actions/tool-cache": { 197 | "version": "2.0.1", 198 | "resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-2.0.1.tgz", 199 | "integrity": "sha512-iPU+mNwrbA8jodY8eyo/0S/QqCKDajiR8OxWTnSk/SnYg0sj8Hp4QcUEVC1YFpHWXtrfbQrE13Jz4k4HXJQKcA==", 200 | "requires": { 201 | "@actions/core": "^1.2.6", 202 | "@actions/exec": "^1.0.0", 203 | "@actions/http-client": "^2.0.1", 204 | "@actions/io": "^1.1.1", 205 | "semver": "^6.1.0", 206 | "uuid": "^3.3.2" 207 | } 208 | }, 209 | "@tsconfig/node20": { 210 | "version": "20.1.2", 211 | "resolved": "https://registry.npmjs.org/@tsconfig/node20/-/node20-20.1.2.tgz", 212 | "integrity": "sha512-madaWq2k+LYMEhmcp0fs+OGaLFk0OenpHa4gmI4VEmCKX4PJntQ6fnnGADVFrVkBj0wIdAlQnK/MrlYTHsa1gQ==", 213 | "dev": true 214 | }, 215 | "@types/node": { 216 | "version": "20.8.9", 217 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", 218 | "integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==", 219 | "dev": true, 220 | "requires": { 221 | "undici-types": "~5.26.4" 222 | } 223 | }, 224 | "@vercel/ncc": { 225 | "version": "0.38.1", 226 | "resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.38.1.tgz", 227 | "integrity": "sha512-IBBb+iI2NLu4VQn3Vwldyi2QwaXt5+hTyh58ggAMoCGE6DJmPvwL3KPBWcJl1m9LYPChBLE980Jw+CS4Wokqxw==", 228 | "dev": true 229 | }, 230 | "prettier": { 231 | "version": "3.0.3", 232 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", 233 | "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", 234 | "dev": true 235 | }, 236 | "semver": { 237 | "version": "6.3.1", 238 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", 239 | "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" 240 | }, 241 | "tunnel": { 242 | "version": "0.0.6", 243 | "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", 244 | "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==" 245 | }, 246 | "typescript": { 247 | "version": "5.2.2", 248 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", 249 | "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", 250 | "dev": true 251 | }, 252 | "undici-types": { 253 | "version": "5.26.5", 254 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", 255 | "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", 256 | "dev": true 257 | }, 258 | "uuid": { 259 | "version": "3.4.0", 260 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", 261 | "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" 262 | } 263 | } 264 | } 265 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "setup-tinygo", 3 | "version": "1.0.0", 4 | "description": "Setup TinyGo for GitHub actions", 5 | "main": "lib/index.js", 6 | "scripts": { 7 | "build": "tsc && ncc build", 8 | "format": "prettier --write **/*.ts" 9 | }, 10 | "keywords": [], 11 | "author": "Alessandro Cifani ", 12 | "license": "MIT", 13 | "dependencies": { 14 | "@actions/core": "^1.10.1", 15 | "@actions/tool-cache": "^2.0.1" 16 | }, 17 | "devDependencies": { 18 | "@tsconfig/node20": "^20.1.2", 19 | "@types/node": "^20.8.9", 20 | "@vercel/ncc": "^0.38.1", 21 | "prettier": "^3.0.3", 22 | "typescript": "^5.2.2" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/binaryen/install.ts: -------------------------------------------------------------------------------- 1 | import * as core from '@actions/core'; 2 | import * as io from '@actions/io'; 3 | import * as tool from '@actions/tool-cache'; 4 | import path from 'path'; 5 | import { printCommand } from '../utils'; 6 | import { getArch, getPlatform } from './sys'; 7 | 8 | const toolName = 'binaryen'; 9 | const arch = getArch(); 10 | const platform = getPlatform(); 11 | 12 | export async function installBinaryen(version: string): Promise { 13 | const installPath = await extract(version); 14 | return addToPath(installPath, version); 15 | } 16 | 17 | async function extract(version: string): Promise { 18 | core.debug(`Checking cache for binaryen v${version} ${arch}`); 19 | const cachedDirectory = tool.find(toolName, version, arch); 20 | if (cachedDirectory) { 21 | // tool version found in cache 22 | return cachedDirectory; 23 | } 24 | 25 | core.debug(`Downloading binaryen v${version} for ${platform} ${arch}`); 26 | try { 27 | const downloadPath = await download(version); 28 | const extractedPath = await extractArchive(downloadPath); 29 | const cachedPath = await tool.cacheDir( 30 | extractedPath, 31 | toolName, 32 | version, 33 | arch, 34 | ); 35 | 36 | return cachedPath; 37 | } catch (error: any) { 38 | throw new Error(`Failed to download version ${version}: ${error}`); 39 | } 40 | } 41 | 42 | async function download(version: string): Promise { 43 | const downloadURL = `https://github.com/WebAssembly/binaryen/releases/download/version_${version}/binaryen-version_${version}-${arch}-${platform}.tar.gz`; 44 | core.debug(`Downloading from ${downloadURL}`); 45 | const downloadPath = await tool.downloadTool(downloadURL); 46 | core.debug(`Downloaded binaryen release to ${downloadPath}`); 47 | return downloadPath; 48 | } 49 | 50 | async function extractArchive(downloadPath: string): Promise { 51 | return tool.extractTar(downloadPath); 52 | } 53 | 54 | async function addToPath(installDir: string, version: string) { 55 | const binaryen = `binaryen-version_${version}`; 56 | core.info(`Adding ${installDir}/${binaryen}/bin to PATH`); 57 | core.addPath(path.join(installDir, binaryen, 'bin')); 58 | const found = await io.findInPath('wasm-opt'); 59 | core.debug(`Found in path: ${found}`); 60 | const wasmopt = await io.which('wasm-opt'); 61 | printCommand(`${wasmopt} --version`); 62 | } 63 | -------------------------------------------------------------------------------- /src/binaryen/sys.ts: -------------------------------------------------------------------------------- 1 | import os from 'os'; 2 | 3 | const platformMap: Record = { 4 | win32: 'windows', 5 | darwin: 'macos', 6 | }; 7 | 8 | export function getPlatform(): string { 9 | const platform = os.platform(); 10 | return platformMap[platform] ?? platform; 11 | } 12 | 13 | export function getArch(): string { 14 | const arch = os.arch(); 15 | return arch === 'x64' ? 'x86_64' : arch; 16 | } 17 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import * as core from '@actions/core'; 2 | import { installBinaryen } from './binaryen/install'; 3 | import { installTinyGo } from './tinygo/install'; 4 | 5 | setup(); 6 | 7 | async function setup() { 8 | try { 9 | const tinyGoVersion = core.getInput('tinygo-version'); 10 | core.info(`Setting up tinygo version ${tinyGoVersion}`); 11 | await installTinyGo(tinyGoVersion); 12 | 13 | const shouldInstallBinaryen = core.getInput('install-binaryen'); 14 | if (shouldInstallBinaryen === 'false') { 15 | core.info('Skipping binaryen installation'); 16 | } else { 17 | const binaryenVersion = core.getInput('binaryen-version'); 18 | core.info(`Setting up binaryen version ${binaryenVersion}`); 19 | await installBinaryen(binaryenVersion); 20 | } 21 | } catch (error: any) { 22 | core.setFailed(error.message); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/tinygo/install.ts: -------------------------------------------------------------------------------- 1 | import * as core from '@actions/core'; 2 | import * as io from '@actions/io'; 3 | import * as tool from '@actions/tool-cache'; 4 | import path from 'path'; 5 | import { printCommand } from '../utils'; 6 | import { getArch, getPlatform } from './sys'; 7 | 8 | const toolName = 'tinygo'; 9 | const arch = getArch(); 10 | const platform = getPlatform(); 11 | 12 | export async function installTinyGo(version: string): Promise { 13 | const installPath = await extract(version); 14 | return addToPath(installPath); 15 | } 16 | 17 | async function extract(version: string): Promise { 18 | core.debug(`Checking cache for tinygo v${version} ${arch}`); 19 | const cachedDirectory = tool.find(toolName, version, arch); 20 | if (cachedDirectory) { 21 | // tool version found in cache 22 | return cachedDirectory; 23 | } 24 | 25 | core.debug(`Downloading tinygo v${version} for ${platform} ${arch}`); 26 | try { 27 | const downloadPath = await download(version); 28 | const extractedPath = await extractArchive(downloadPath); 29 | const cachedPath = await tool.cacheDir( 30 | extractedPath, 31 | toolName, 32 | version, 33 | arch, 34 | ); 35 | 36 | return cachedPath; 37 | } catch (error: any) { 38 | throw new Error(`Failed to download version ${version}: ${error}`); 39 | } 40 | } 41 | 42 | async function download(version: string): Promise { 43 | const extension = platform === 'windows' ? 'zip' : 'tar.gz'; 44 | const downloadURL = `https://github.com/tinygo-org/tinygo/releases/download/v${version}/tinygo${version}.${platform}-${arch}.${extension}`; 45 | core.debug(`Downloading from ${downloadURL}`); 46 | const downloadPath = await tool.downloadTool(downloadURL); 47 | core.debug(`Downloaded tinygo release to ${downloadPath}`); 48 | return downloadPath; 49 | } 50 | 51 | async function extractArchive(downloadPath: string): Promise { 52 | let extractedPath = ''; 53 | if (platform === 'windows') { 54 | extractedPath = await tool.extractZip(downloadPath); 55 | } else { 56 | extractedPath = await tool.extractTar(downloadPath); 57 | } 58 | 59 | return extractedPath; 60 | } 61 | 62 | async function addToPath(installDir: string) { 63 | core.info(`Adding ${installDir}/tinygo/bin to PATH`); 64 | core.addPath(path.join(installDir, 'tinygo', 'bin')); 65 | const found = await io.findInPath('tinygo'); 66 | core.debug(`Found in path: ${found}`); 67 | const tinygo = await io.which('tinygo'); 68 | printCommand(`${tinygo} version`); 69 | printCommand(`${tinygo} env`); 70 | } 71 | -------------------------------------------------------------------------------- /src/tinygo/sys.ts: -------------------------------------------------------------------------------- 1 | import os from 'os'; 2 | 3 | export function getPlatform(): string { 4 | const platform = os.platform(); 5 | return platform === 'win32' ? 'windows' : platform; 6 | } 7 | 8 | export function getArch(): string { 9 | const arch = os.arch(); 10 | return arch === 'x64' ? 'amd64' : arch; 11 | } 12 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | import * as core from '@actions/core'; 2 | import cp from 'child_process'; 3 | 4 | export function printCommand(command: string) { 5 | const output = cp.execSync(command).toString(); 6 | core.info(output); 7 | } 8 | -------------------------------------------------------------------------------- /test-binaryen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Checks that Binaryen is not installed 4 | if [ -x "$(command -v wasm-opt)" ]; then 5 | echo 'Error: Binaryen is installed.' >&2 6 | exit 1 7 | fi 8 | -------------------------------------------------------------------------------- /test-build.sh: -------------------------------------------------------------------------------- 1 | tinygo build -o wasm.wasm -target wasm ./test/test.go 2 | -------------------------------------------------------------------------------- /test/test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("hello tinygo") 7 | } 8 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/node20/tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "lib" 5 | } 6 | } 7 | --------------------------------------------------------------------------------