Skip to content
Open
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
92 changes: 69 additions & 23 deletions scripts/lint.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ function getPlatformArch() {
shellcheck: 'darwin.aarch64',
};
}
if (platform === 'win32' && arch === 'x64') {
return {
actionlint: 'windows_amd64',
shellcheck: 'win.x86_64',
};
}
throw new Error(`Unsupported platform/architecture: ${platform}/${arch}`);
}

Expand All @@ -58,10 +64,52 @@ const pythonVenvPythonPath = join(
process.platform === 'win32' ? 'python.exe' : 'python',
);

const yamllintCheck =
process.platform === 'win32'
? `if exist "${PYTHON_VENV_PATH}\\Scripts\\yamllint.exe" (exit 0) else (exit 1)`
: `test -x "${PYTHON_VENV_PATH}/bin/yamllint"`;
const isWindows = process.platform === 'win32';

const actionlintCheck = isWindows
? `where actionlint 2>nul`
: 'command -v actionlint';

const actionlintInstaller = isWindows
? `powershell -Command "` +
`New-Item -ItemType Directory -Force -Path '${TEMP_DIR}/actionlint' | Out-Null; ` +
`Invoke-WebRequest -Uri 'https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION}_${platformArch.actionlint}.zip' -OutFile '${TEMP_DIR}/.actionlint.zip'; ` +
`Add-Type -AssemblyName System.IO.Compression.FileSystem; ` +
`[System.IO.Compression.ZipFile]::ExtractToDirectory('${TEMP_DIR}/.actionlint.zip', '${TEMP_DIR}/actionlint')"`
: `
mkdir -p "${TEMP_DIR}/actionlint"
curl -sSLo "${TEMP_DIR}/.actionlint.tgz" "https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION}_${platformArch.actionlint}.tar.gz"
tar -xzf "${TEMP_DIR}/.actionlint.tgz" -C "${TEMP_DIR}/actionlint"
`;

const shellcheckCheck = isWindows
? `where shellcheck 2>nul`
: 'command -v shellcheck';

const shellcheckInstaller = isWindows
? `powershell -Command "` +
`Invoke-WebRequest -Uri 'https://github.com/koalaman/shellcheck/releases/download/v${SHELLCHECK_VERSION}/shellcheck-v${SHELLCHECK_VERSION}.zip' -OutFile '${TEMP_DIR}/.shellcheck.zip'; ` +
`Add-Type -AssemblyName System.IO.Compression.FileSystem; ` +
`[System.IO.Compression.ZipFile]::ExtractToDirectory('${TEMP_DIR}/.shellcheck.zip', '${TEMP_DIR}/shellcheck')"`
Comment on lines +90 to +93
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The Windows installer for shellcheck has a couple of issues that will prevent it from working correctly:

  1. Incorrect URL: The download URL is hardcoded to .../shellcheck-v${SHELLCHECK_VERSION}.zip, which will result in a 404 error. The URL needs to include the platform and architecture, similar to the other installers. The correct asset for Windows is named like shellcheck-vX.Y.Z.win.x86_64.zip.
  2. Incorrect Executable Name: The zip file contains a versioned executable (e.g., shellcheck-v0.11.0.exe). After extraction, the script will look for shellcheck.exe in the PATH and fail to find it. The installer needs to rename the executable to shellcheck.exe after extraction.

I've included a suggestion that also adds a New-Item command for consistency with the actionlint installer and fixes both issues.

  ? `powershell -Command "` +
    `New-Item -ItemType Directory -Force -Path '${TEMP_DIR}/shellcheck' | Out-Null; ` +
    `Invoke-WebRequest -Uri 'https://github.com/koalaman/shellcheck/releases/download/v${SHELLCHECK_VERSION}/shellcheck-v${SHELLCHECK_VERSION}.${platformArch.shellcheck}.zip' -OutFile '${TEMP_DIR}/.shellcheck.zip'; ` +
    `Add-Type -AssemblyName System.IO.Compression.FileSystem; ` +
    `[System.IO.Compression.ZipFile]::ExtractToDirectory('${TEMP_DIR}/.shellcheck.zip', '${TEMP_DIR}/shellcheck'); ` +
    `Move-Item -Path '${TEMP_DIR}/shellcheck/shellcheck-v${SHELLCHECK_VERSION}.exe' -Destination '${TEMP_DIR}/shellcheck/shellcheck.exe'"

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

curl -sI "https://github.com/koalaman/shellcheck/releases/download/v0.11.0/shellcheck-v0.11.0.zip"
returns HTTP/1.1 302 Found

curl -sI "https://github.com/koalaman/shellcheck/releases/download/v0.11.0/shellcheck-v0.11.0.win.x86_64.zip"
HTTP/1.1 404 Not Found

image image

: `
mkdir -p "${TEMP_DIR}/shellcheck"
curl -sSLo "${TEMP_DIR}/.shellcheck.txz" "https://github.com/koalaman/shellcheck/releases/download/v${SHELLCHECK_VERSION}/shellcheck-v${SHELLCHECK_VERSION}.${platformArch.shellcheck}.tar.xz"
tar -xf "${TEMP_DIR}/.shellcheck.txz" -C "${TEMP_DIR}/shellcheck" --strip-components=1
`;

const yamllintCheck = isWindows
? `if exist "${PYTHON_VENV_PATH}\\Scripts\\yamllint.exe" (exit 0) else (exit 1)`
: `test -x "${PYTHON_VENV_PATH}/bin/yamllint"`;

const yamllintInstaller = isWindows
? `python -m venv "${PYTHON_VENV_PATH}" && ` +
`"${pythonVenvPythonPath}" -m pip install --upgrade pip && ` +
`"${pythonVenvPythonPath}" -m pip install "yamllint==${YAMLLINT_VERSION}" --index-url https://pypi.org/simple`
: `
python3 -m venv "${PYTHON_VENV_PATH}" && \
"${pythonVenvPythonPath}" -m pip install --upgrade pip && \
"${pythonVenvPythonPath}" -m pip install "yamllint==${YAMLLINT_VERSION}" --index-url https://pypi.org/simple
`;

/**
* @typedef {{
Expand All @@ -76,12 +124,8 @@ const yamllintCheck =
*/
const LINTERS = {
actionlint: {
check: 'command -v actionlint',
installer: `
mkdir -p "${TEMP_DIR}/actionlint"
curl -sSLo "${TEMP_DIR}/.actionlint.tgz" "https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION}_${platformArch.actionlint}.tar.gz"
tar -xzf "${TEMP_DIR}/.actionlint.tgz" -C "${TEMP_DIR}/actionlint"
`,
check: actionlintCheck,
installer: actionlintInstaller,
run: `
actionlint \
-color \
Expand All @@ -92,12 +136,8 @@ const LINTERS = {
`,
},
shellcheck: {
check: 'command -v shellcheck',
installer: `
mkdir -p "${TEMP_DIR}/shellcheck"
curl -sSLo "${TEMP_DIR}/.shellcheck.txz" "https://github.com/koalaman/shellcheck/releases/download/v${SHELLCHECK_VERSION}/shellcheck-v${SHELLCHECK_VERSION}.${platformArch.shellcheck}.tar.xz"
tar -xf "${TEMP_DIR}/.shellcheck.txz" -C "${TEMP_DIR}/shellcheck" --strip-components=1
`,
check: shellcheckCheck,
installer: shellcheckInstaller,
run: `
git ls-files | grep -E '^([^.]+|.*\\.(sh|zsh|bash))' | xargs file --mime-type \
| grep "text/x-shellscript" | awk '{ print substr($1, 1, length($1)-1) }' \
Expand All @@ -112,11 +152,7 @@ const LINTERS = {
},
yamllint: {
check: yamllintCheck,
installer: `
python3 -m venv "${PYTHON_VENV_PATH}" && \
"${pythonVenvPythonPath}" -m pip install --upgrade pip && \
"${pythonVenvPythonPath}" -m pip install "yamllint==${YAMLLINT_VERSION}" --index-url https://pypi.org/simple
`,
installer: yamllintInstaller,
run: "git ls-files | grep -E '\\.(yaml|yml)' | xargs yamllint --format github",
},
};
Expand All @@ -125,8 +161,18 @@ function runCommand(command, stdio = 'inherit') {
try {
const env = { ...process.env };
const nodeBin = join(process.cwd(), 'node_modules', '.bin');
env.PATH = `${nodeBin}:${TEMP_DIR}/actionlint:${TEMP_DIR}/shellcheck:${PYTHON_VENV_PATH}/bin:${env.PATH}`;
execSync(command, { stdio, env });
const sep = isWindows ? ';' : ':';
const pythonBin = isWindows
? join(PYTHON_VENV_PATH, 'Scripts')
: join(PYTHON_VENV_PATH, 'bin');
env.PATH = [
nodeBin,
join(TEMP_DIR, 'actionlint'),
join(TEMP_DIR, 'shellcheck'),
pythonBin,
env.PATH,
].join(sep);
execSync(command, { stdio, env, shell: true });
return true;
} catch (_e) {
return false;
Expand Down