-
-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
create standalone action for wsl steps
- Loading branch information
1 parent
9259b3c
commit 76cee5b
Showing
5 changed files
with
283 additions
and
57 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
node_modules/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
name: 'WSL Run Action' | ||
description: 'Runs GitHub actions in WSL environment' | ||
inputs: | ||
uses: | ||
description: 'The action to run in WSL' | ||
required: false | ||
with: | ||
description: 'Input parameters for the action' | ||
required: false | ||
run: | ||
description: 'Commands to run in WSL bash shell' | ||
required: false | ||
runs: | ||
using: 'node20' | ||
main: 'wsl-run-action.js' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
{ | ||
"name": "wsl-run-action", | ||
"version": "1.0.0", | ||
"description": "GitHub action to run commands or other actions in WSL environment", | ||
"main": "wsl-run-action.js", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"keywords": [ | ||
"github", | ||
"action", | ||
"wsl" | ||
], | ||
"author": "", | ||
"license": "MIT", | ||
"dependencies": { | ||
"@actions/core": "^1.10.1", | ||
"@actions/exec": "^1.1.1" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
/** | ||
* GitHub action to run other actions in WSL environment | ||
* @param {string} uses - Name of GitHub action to run (e.g. 'actions/checkout@v4') | ||
* @param {string} with - Input parameters to pass to the action in key=value format, supporting =, :, and = delimiters | ||
* @param {string} run - Commands to run in WSL bash shell | ||
* @return {Promise<void>} Promise that resolves when action completes | ||
*/ | ||
const core = require('@actions/core'); | ||
const exec = require('@actions/exec'); | ||
|
||
// Define WSL environment variables once at the top level | ||
const baseWslEnv = [ | ||
'GITHUB_WORKSPACE/p', | ||
'GITHUB_ACTION', | ||
'GITHUB_ACTIONS', | ||
'GITHUB_ACTOR', | ||
'GITHUB_REPOSITORY', | ||
'GITHUB_EVENT_NAME', | ||
'GITHUB_EVENT_PATH/p', | ||
'GITHUB_SHA', | ||
'GITHUB_REF', | ||
'GITHUB_TOKEN', | ||
'GITHUB_RUN_ID', | ||
'GITHUB_RUN_NUMBER', | ||
'RUNNER_OS', | ||
'RUNNER_TEMP/p', | ||
'RUNNER_TOOL_CACHE/p', | ||
'CI', | ||
'GITHUB_DEBUG', | ||
'ACTIONS_RUNNER_DEBUG', | ||
'ACTIONS_STEP_DEBUG' | ||
]; | ||
|
||
async function run() { | ||
try { | ||
// Get action inputs | ||
const uses = core.getInput('uses'); | ||
const withInputs = core.getInput('with'); | ||
const runCommand = core.getInput('run'); | ||
|
||
// Validate inputs | ||
if (runCommand && (uses || withInputs)) { | ||
throw new Error('The "run" input cannot be used together with "uses" or "with" inputs'); | ||
} | ||
|
||
if (!runCommand && !uses) { | ||
throw new Error('Either "run" or "uses" input must be provided'); | ||
} | ||
|
||
// If run command is provided, execute it directly in WSL | ||
if (runCommand) { | ||
core.info('Running command in WSL environment'); | ||
core.debug(`Command: ${runCommand}`); | ||
|
||
// Set up basic environment variables for WSL | ||
const wslEnv = baseWslEnv.join(':'); | ||
|
||
process.env.WSLENV = process.env.WSLENV ? `${process.env.WSLENV}:${wslEnv}` : wslEnv; | ||
|
||
await exec.exec('wsl.exe', ['bash', '-c', runCommand], { | ||
env: process.env | ||
}); | ||
|
||
core.info('Command completed successfully'); | ||
return; | ||
} | ||
|
||
// Original action execution logic for 'uses' | ||
core.info(`Running action ${uses} in WSL environment`); | ||
|
||
// Parse action name and version | ||
const [owner, repo, version] = uses.split(/[@/]/g); | ||
core.debug(`Parsed action: owner=${owner}, repo=${repo}, version=${version}`); | ||
|
||
// Set up environment variables from with inputs | ||
const env = {}; | ||
if (withInputs) { | ||
core.debug('Parsing with inputs:'); | ||
core.debug(withInputs); | ||
|
||
// Parse key-value pairs with flexible delimiters | ||
const inputs = withInputs | ||
.split(/[\n,]/) | ||
.map(line => line.trim()) | ||
.filter(line => line.length > 0) | ||
.reduce((acc, line) => { | ||
const match = line.match(/^([^=:]+)(?:=|\s*:\s*|\s+=\s+)(.+)$/); | ||
if (match) { | ||
const [, key, value] = match; | ||
acc[key.trim()] = value.trim(); | ||
} | ||
return acc; | ||
}, {}); | ||
|
||
for (const [key, value] of Object.entries(inputs)) { | ||
const envKey = `INPUT_${key.toUpperCase().replace(/-/g, '_')}`; | ||
env[envKey] = value; | ||
core.debug(`Setting env var: ${envKey}=${value}`); | ||
} | ||
} | ||
|
||
// Add environment variables to WSLENV | ||
const wslEnv = [ | ||
...baseWslEnv, | ||
...Object.keys(env).map(key => key.slice(6)) | ||
].join(':'); | ||
|
||
process.env.WSLENV = process.env.WSLENV ? `${process.env.WSLENV}:${wslEnv}` : wslEnv; | ||
core.debug(`Set WSLENV: ${process.env.WSLENV}`); | ||
|
||
// Clone and install the action in WSL | ||
core.info('Cloning and installing action in WSL...'); | ||
await exec.exec('wsl.exe', ['bash', '-c', ` | ||
set -e | ||
mkdir -p ~/actions/${owner}/${repo} | ||
cd ~/actions/${owner}/${repo} | ||
git clone --depth 1 --branch ${version} https://github.com/${owner}/${repo}.git . | ||
# Install dependencies if needed | ||
if [ -f "package.json" ]; then | ||
npm install | ||
npm run build || true | ||
fi | ||
# First check for dist/index.js | ||
if [ -f "dist/index.js" ]; then | ||
echo "MAIN_FILE=dist/index.js" >> $GITHUB_ENV | ||
else | ||
# Fall back to checking action.yml for entry point | ||
for action_file in action.yml action.yaml; do | ||
if [ -f "$action_file" ]; then | ||
MAIN_FILE=$(grep "main:" "$action_file" | sed 's/main:[[:space:]]*//;s/^["'\'']*//;s/["'\''].*$//') | ||
if [ ! -z "$MAIN_FILE" ]; then | ||
echo "Entry point from $action_file: $MAIN_FILE" | ||
echo "MAIN_FILE=$MAIN_FILE" >> $GITHUB_ENV | ||
break | ||
fi | ||
fi | ||
done | ||
fi | ||
`], { | ||
env: { | ||
...process.env, | ||
...env | ||
} | ||
}); | ||
|
||
// Run the action | ||
core.info('Running action...'); | ||
const debugScript = process.env.GITHUB_DEBUG === 'true' ? 'env' : ''; | ||
await exec.exec('wsl.exe', ['bash', '-c', ` | ||
set -e | ||
cd ~/actions/${owner}/${repo} | ||
${debugScript} | ||
if [ -f "$MAIN_FILE" ]; then | ||
node "$MAIN_FILE" | ||
else | ||
echo "Could not find entry point at $MAIN_FILE. Contents of directory:" | ||
ls -R | ||
exit 1 | ||
fi | ||
`], { | ||
env: { | ||
...process.env, | ||
...env | ||
} | ||
}); | ||
|
||
core.info('Action completed successfully'); | ||
|
||
} catch (error) { | ||
core.error('Action failed with error:'); | ||
core.error(error); | ||
core.setFailed(error.message); | ||
} | ||
} | ||
|
||
run(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,10 +18,6 @@ jobs: | |
- "20" | ||
os: | ||
- windows-2022 | ||
defaults: | ||
run: | ||
# Actions passes commands as a script with windows line endings, so we need to convert them to unix line endings | ||
shell: wsl.exe bash --noprofile --norc -euo pipefail -c "touch ~/.env && source ~/.env; GITHUB_TOKEN=${{ github.token }} RUNNER_DEBUG=${{ env.RUNNER_DEBUG }} exec $(script="$(wslpath '{0}')" && sed -i 's/\r$//' "$script" && echo "$script")" | ||
|
||
steps: | ||
- name: Install Ubuntu for WSL2 | ||
|
@@ -39,66 +35,84 @@ jobs: | |
Invoke-WebRequest -Uri $downloadUrl -OutFile $filename | ||
Expand-Archive -Path $filename -DestinationPath .\ | ||
.\ubuntu.exe install --root | ||
- name: Setup Ubuntu Shell Environment | ||
shell: pwsh | ||
run: | | ||
$envVars = @" | ||
export CI=true | ||
export GITHUB_ACTIONS=true | ||
export GITHUB_WORKSPACE=$(wsl.exe wslpath -a "$env:GITHUB_WORKSPACE") | ||
export RUNNER_OS=Linux | ||
export RUNNER_TEMP=$(wsl.exe wslpath -a "$env:RUNNER_TEMP") | ||
export RUNNER_TOOL_CACHE=$(wsl.exe wslpath -a "$env:RUNNER_TOOL_CACHE") | ||
"@ | ||
wsl.exe bash -c "echo '$envVars' > ~/.env" | ||
- name: Checkout code | ||
uses: actions/checkout@v4 | ||
with: | ||
fetch-depth: 1 | ||
ref: ${{ github.sha }} | ||
|
||
- name: Setup WSL Run Action | ||
shell: pwsh | ||
run: | | ||
git clone --depth 1 --single-branch https://github.com/${{ github.repository }}.git . | ||
git fetch --depth 1 origin ${{ github.sha }} | ||
git checkout ${{ github.sha }} | ||
cd .github/actions/wsl-run | ||
npm install | ||
# Install Node.js and git in WSL environment | ||
wsl.exe bash -c "curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && apt-get install -y nodejs git" | ||
- name: Install node ${{ matrix.node-version }} | ||
run: | | ||
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash | ||
echo 'export NVM_DIR="$HOME/.nvm"' >> ~/.env | ||
echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> ~/.env | ||
source ~/.env | ||
nvm install ${{ matrix.node-version }} | ||
uses: ./.github/actions/wsl-run | ||
with: | ||
uses: actions/setup-node@v4 | ||
with: | | ||
node-version: ${{ matrix.node-version }} | ||
- name: Bundle Deps | ||
run: | | ||
mkdir -p ~/prepare-release-action | ||
git clone --depth 1 https://github.com/lando/prepare-release-action.git ~/prepare-release-action | ||
cd ~/prepare-release-action | ||
export INPUT_PLUGIN=true | ||
export INPUT_VERSION=dev | ||
export INPUT_SYNC=false | ||
export INPUT_BUNDLE-DEPENDENCIES=true | ||
node dist/index.js | ||
uses: ./.github/actions/wsl-run | ||
with: | ||
run: | | ||
mkdir -p ~/prepare-release-action | ||
git clone --depth 1 https://github.com/lando/prepare-release-action.git ~/prepare-release-action | ||
cd ~/prepare-release-action | ||
env \ | ||
INPUT_LANDO-PLUGIN=true \ | ||
INPUT_VERSION=dev \ | ||
INPUT_SYNC=false \ | ||
INPUT_BUNDLE-DEPENDENCIES=true \ | ||
node dist/index.js | ||
- name: Install pkg dependencies | ||
run: npm clean-install --prefer-offline --frozen-lockfile --production | ||
uses: ./.github/actions/wsl-run | ||
with: | ||
run: npm clean-install --prefer-offline --frozen-lockfile --production | ||
|
||
- name: Package into node binary | ||
uses: ./.github/actions/wsl-run | ||
id: pkg-action | ||
run: | | ||
npm install -g @yao-pkg/[email protected] | ||
pkg bin/lando --target node${{ matrix.node-version }}-linux-x64 --options dns-result-order=ipv4first --output lando | ||
echo "PKG_OUTPUT=lando" >> ${{ github.env }} | ||
with: | ||
run: | | ||
npm install -g @yao-pkg/[email protected] | ||
pkg bin/lando --target node${{ matrix.node-version }}-linux-x64 --options dns-result-order=ipv4first --output lando | ||
echo "PKG_OUTPUT=lando" >> $GITHUB_ENV | ||
- name: Install full deps | ||
run: npm clean-install --prefer-offline --frozen-lockfile | ||
uses: ./.github/actions/wsl-run | ||
with: | ||
run: npm clean-install --prefer-offline --frozen-lockfile | ||
|
||
- name: Setup lando ${{ steps.pkg-action.outputs.file }} | ||
run: | | ||
mkdir -p ~/setup-lando | ||
git clone --depth 1 https://github.com/lando/setup-lando.git ~/setup-lando | ||
cd ~/setup-lando | ||
export INPUT_AUTO_SETUP=false | ||
export INPUT_LANDO_VERSION="${{ steps.pkg-action.outputs.file }}" | ||
export INPUT_TELEMETRY=false | ||
node dist/index.js | ||
uses: ./.github/actions/wsl-run | ||
with: | ||
run: | | ||
mkdir -p ~/setup-lando | ||
git clone --depth 1 https://github.com/lando/setup-lando.git ~/setup-lando | ||
cd ~/setup-lando | ||
env \ | ||
INPUT_AUTO-SETUP=false \ | ||
INPUT_LANDO-VERSION="${{ steps.pkg-action.outputs.file }}" \ | ||
INPUT_TELEMETRY=false \ | ||
node dist/index.js | ||
- name: Run Leia Tests | ||
run: | | ||
mkdir -p ~/run-leia-action | ||
git clone --depth 1 https://github.com/lando/run-leia-action.git ~/run-leia-action | ||
cd ~/run-leia-action | ||
export INPUT_LEIA_TEST="./examples/${{ matrix.leia-test }}/README.md" | ||
export INPUT_CLEANUP_HEADER="Destroy tests" | ||
export INPUT_SHELL="bash" | ||
export INPUT_STDIN=true | ||
node dist/index.js | ||
uses: ./.github/actions/wsl-run | ||
with: | ||
run: | | ||
mkdir -p ~/run-leia-action | ||
git clone --depth 1 https://github.com/lando/run-leia-action.git ~/run-leia-action | ||
cd ~/run-leia-action | ||
env \ | ||
INPUT_LEIA-TEST="./examples/${{ matrix.leia-test }}/README.md" \ | ||
INPUT_CLEANUP-HEADER="Destroy tests" \ | ||
INPUT_SHELL="bash" \ | ||
INPUT_STDIN=true \ | ||
node dist/index.js |