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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions .github/actions/setup-tinygo/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: 'Setup TinyGo environment'
description: 'Setup a TinyGo environment and add it to the PATH'
inputs:
version:
description: 'The Go version to download and use. Must be a valid commitish, e.g. "dev" or "v1.0.0"'
required: true
runs:
using: "composite"
steps:
- name: Install LLVM 13
run: |
source /etc/os-release
echo "deb http://apt.llvm.org/${UBUNTU_CODENAME}/ llvm-toolchain-${UBUNTU_CODENAME}-13 main" | sudo tee /etc/apt/sources.list.d/llvm.list
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
sudo apt-get -qq update
sudo apt-get -yqq install clang-13 llvm-13-dev lld-13 libclang-13-dev
shell: bash

- uses: actions/setup-go@v3
with:
go-version: 1.18

- name: Install Binaryen
run: |
pushd /dev/shm
VERSION="$(curl -fsSLI -o /dev/null -w "%{url_effective}" https://github.com/WebAssembly/binaryen/releases/latest)"
VERSION="${VERSION#https://github.com/WebAssembly/binaryen/releases/tag/}"
curl -sfOL "https://github.com/WebAssembly/binaryen/releases/download/${VERSION}/binaryen-${VERSION}-$(uname -m)-linux.tar.gz"
tar -xvf "binaryen-${VERSION}-$(uname -m)-linux.tar.gz"
mkdir -p "${RUNNER_TOOL_CACHE}/binaryen"
mv "binaryen-${VERSION}" "${RUNNER_TOOL_CACHE}/binaryen/${VERSION}"
echo "${RUNNER_TOOL_CACHE}/binaryen/${VERSION}/bin" >> $GITHUB_PATH
popd
shell: bash

- name: Install TinyGo
run: |
pushd /dev/shm
mkdir tinygo
cd tinygo
git init
git remote add origin https://github.com/tinygo-org/tinygo.git
git fetch --prune --progress --no-tags --depth=1 origin "${{ inputs.version }}"
git checkout --progress --force -B "${{ inputs.version }}" FETCH_HEAD
git submodule update --init --recursive --depth 1
make wasi-libc
mkdir -p "${RUNNER_TOOL_CACHE}/tinygo/${{ inputs.version }}"
GOBIN="${RUNNER_TOOL_CACHE}/tinygo/${{ inputs.version }}" go install
echo "${RUNNER_TOOL_CACHE}/tinygo/${{ inputs.version }}" >> $GITHUB_PATH
popd
shell: bash
14 changes: 8 additions & 6 deletions .github/workflows/push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ jobs:
steps:
- uses: actions/checkout@v3

- name: Setup Go
uses: actions/setup-go@v3
- name: Setup TinyGo
uses: ./.github/actions/setup-tinygo
with:
version: fce42fc7fa22f9a8061ef8700e2d17a6082f782e # latest commit on dev at the time of writing

- name: Setup Node
uses: actions/setup-node@v3
Expand Down Expand Up @@ -41,10 +43,10 @@ jobs:

cat << EOF > test.mjs
import { createLinter } from 'actionlint';
createLinter()('on: psuh', 'push.yml').then(
(results) => process.exit(results.length > 0 ? 0 : 1),
(err) => { console.error(err); process.exit(1); }
);
createLinter().then(lint => {
const results = lint('on: psuh', 'push.yml');
process.exit(results.length > 0 ? 0 : 1)
}, (err) => { console.error(err); process.exit(1); });
EOF

# test that the linter works
Expand Down
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
main.wasm
wasm_exec.js
tmp.wasm
node_modules/
types/
types/
3 changes: 2 additions & 1 deletion .npmignore
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
.github/
.vscode/
node_modules/
go.mod
go.sum
globals.d.ts
main.go
Makefile
renovate.json
test.mjs
tmp.wasm
tsconfig.json
yarn.lock
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
"GOARCH": "wasm"
}
}
}
}
17 changes: 7 additions & 10 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
build: wasm_exec.js main.wasm types/node.d.mts
build: main.wasm types/node.d.mts

wasm_exec.js:
cp $$(go env GOROOT)/misc/wasm/wasm_exec.js wasm_exec.tmp.js
echo "// @ts-nocheck" > wasm_exec.js
cat wasm_exec.tmp.js >> wasm_exec.js
rm wasm_exec.tmp.js
main.wasm: tmp.wasm
wasm-opt -c -O4 -o main.wasm tmp.wasm

main.wasm: main.go go.mod
GOOS=js GOARCH=wasm go build -o main.wasm
tmp.wasm: main.go go.mod
tinygo build -o tmp.wasm -target wasm -panic trap -opt z main.go

types/node.d.mts: *.cjs *.mjs *.d.ts *.json yarn.lock
$$(yarn bin)/tsc -p .

clean:
rm main.wasm
rm wasm_exec.js
rm tmp.wasm
rm -rf types

.PHONY: build clean
.PHONY: build clean
96 changes: 55 additions & 41 deletions actionlint.cjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
require("./wasm_exec.js");
require("./tiny_wasm_exec.js");

/**
* @typedef {(go: Go) => Promise<WebAssembly.WebAssemblyInstantiatedSource>} WasmLoader
Expand All @@ -8,54 +8,68 @@ require("./wasm_exec.js");

/**
* @param {WasmLoader} loader
* @returns {RunActionlint}
* @returns {Promise<RunActionlint>}
*/
module.exports.createActionlint = function createActionlint(loader) {
module.exports.createActionlint = async function createActionlint(loader) {
const encoder = new TextEncoder();
const decoder = new TextDecoder();
const go = new Go();

/** @type {(() => void)[] | undefined} */
let queued = undefined;
const wasm = await loader(go);
// Do not await this promise, because it only resolves once the go main()
// function has exited. But we need the main function to stay alive to be
// able to call the `runActionlint` function.
go.run(wasm.instance);

// This function gets called from go once the wasm module is ready and it
// executes the linter for all queued calls.
globalThis.actionlintInitialized = () => {
queued?.forEach((f) => f());
queued = globalThis.actionlintInitialized = undefined;
};
const { memory, WasmAlloc, WasmFree, RunActionlint } = wasm.instance.exports;

loader(go).then((wasm) => {
// Do not await this promise, because it only resolves once the go main()
// function has exited. But we need the main function to stay alive to be
// able to call the `runActionlint` function.
go.run(wasm.instance);
});
if (
!(memory instanceof WebAssembly.Memory) ||
!(WasmAlloc instanceof Function) ||
!(WasmFree instanceof Function) ||
!(RunActionlint instanceof Function)
) {
throw new Error(
"Invalid wasm exports. Expected memory, WasmAlloc, WasmFree, RunActionlint."
);
}

/**
* @param {string} src
* @param {string} input
* @param {string} path
* @returns {Promise<LintResult[]>}
* @returns {LintResult[]}
*/
return async function runLint(src, path) {
// Return a promise, because we need to queue calls to `runLint()` while the
// wasm module is still loading and execute them once the wasm module is
//ready.
return new Promise((resolve, reject) => {
if (typeof runActionlint === "function") {
const [result, err] = runActionlint(src, path);
return err ? reject(err) : resolve(result);
}

if (!queued) {
queued = [];
}

queued.push(() => {
const [result, err] = runActionlint?.(src, path) ?? [
[],
new Error('"runActionlint" is not defined'),
];
return err ? reject(err) : resolve(result);
});
});
return function runLint(input, path) {
const workflow = encoder.encode(input);
const filePath = encoder.encode(path);

const workflowPointer = WasmAlloc(workflow.byteLength);
new Uint8Array(memory.buffer).set(workflow, workflowPointer);

const filePathPointer = WasmAlloc(filePath.byteLength);
new Uint8Array(memory.buffer).set(filePath, filePathPointer);

const resultPointer = RunActionlint(
workflowPointer,
workflow.byteLength,
workflow.byteLength,
filePathPointer,
filePath.byteLength,
filePath.byteLength
);

WasmFree(workflowPointer);
WasmFree(filePathPointer);

const result = new Uint8Array(memory.buffer).subarray(resultPointer);
const end = result.indexOf(0);

const string = decoder.decode(result.subarray(0, end));

try {
return JSON.parse(string);
} catch {
throw new Error(string);
}
};
};
17 changes: 6 additions & 11 deletions browser.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,19 @@ import { createActionlint } from "./actionlint.cjs";
* @typedef {import("./types").LintResult} LintResult
*/

/** @type {RunActionlint | undefined} */
let runLint = undefined;

/**
* @param {URL} url
* @returns {RunActionlint}
* @returns {Promise<RunActionlint>}
*/
export function createLinter(url = new URL("./main.wasm", import.meta.url)) {
if (runLint) {
return runLint;
}

return (runLint = createActionlint(
export async function createLinter(
url = new URL("./main.wasm", import.meta.url)
) {
return await createActionlint(
/** @type {WasmLoader} */ async (go) => {
return WebAssembly.instantiateStreaming(
fetch(url.toString()),
go.importObject
);
}
));
);
}
6 changes: 0 additions & 6 deletions globals.d.ts

This file was deleted.

9 changes: 6 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@ module source.xing.com/fea/act-app

go 1.17

require github.com/rhysd/actionlint v1.6.12

require (
github.com/fatih/color v1.13.0 // indirect
github.com/mattn/go-colorable v0.1.11 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/rhysd/actionlint v1.6.9 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/robfig/cron v1.2.0 // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.0.0-20211113001501-0c823b97ae02 // indirect
golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
)

replace gopkg.in/yaml.v3 => github.com/ZauberNerd/yaml v0.0.0-20220305122605-f022dd71f1c2
25 changes: 17 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,27 +1,36 @@
github.com/ZauberNerd/yaml v0.0.0-20220305122605-f022dd71f1c2 h1:XKY7uPNa/yq6NV/j6HHrAck1Aco1Xlj5Y+bDHnN9HHA=
github.com/ZauberNerd/yaml v0.0.0-20220305122605-f022dd71f1c2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/rhysd/actionlint v1.6.9 h1:8rQQ76o88zctUCzukt0A5O/FO003wTGbkLQuwQkMf9c=
github.com/rhysd/actionlint v1.6.9/go.mod h1:0AA4pvZ2nrZHT6D86eUhieH2NFmLqhxrNex0NEa2A2g=
github.com/rhysd/actionlint v1.6.12 h1:Qoa69UsvF/7tNc0008v7s1hHDANHuqaq0qHhu4syf7w=
github.com/rhysd/actionlint v1.6.12/go.mod h1:M+vAgTIFE2yOdr91fpDF4CUsyZVsPmS+D/x2K7qhhP0=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211113001501-0c823b97ae02 h1:7NCfEGl0sfUojmX78nK9pBJuUlSZWEJA/TwASvfiPLo=
golang.org/x/sys v0.0.0-20211113001501-0c823b97ae02/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f h1:rlezHXNlxYWvBCzNses9Dlc7nGFaNMJeqLolcmQSSZY=
golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Loading