diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..ac7585f --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @dcarbone diff --git a/.github/workflows/example-linux.yaml b/.github/workflows/example-linux.yaml new file mode 100644 index 0000000..2e2cd85 --- /dev/null +++ b/.github/workflows/example-linux.yaml @@ -0,0 +1,36 @@ +name: "Setup jq Example - Linux" + +on: + workflow_dispatch: + inputs: + version: + type: string + required: false + description: "Version of jq to install" + default: "1.6" + download-compressed: + type: boolean + required: false + description: "Download .tar.gz of binary rather than raw binary. Save the tubes." + default: true + force: + type: boolean + required: false + description: "Do not check for existing jq installation before continuing." + default: false + +jobs: + example: + runs-on: ubuntu-latest + steps: + - name: 'Setup jq' + uses: dcarbone/install-jq-action@v1.0.0 + with: + version: '${{ inputs.version }}' + download-compressed: '${{ inputs.download-compressed }}' + force: '${{ inputs.force }}' + + - name: 'Check jq' + run: | + which jq + jq --version diff --git a/.github/workflows/example-macos.yaml b/.github/workflows/example-macos.yaml new file mode 100644 index 0000000..769c218 --- /dev/null +++ b/.github/workflows/example-macos.yaml @@ -0,0 +1,36 @@ +name: "Setup jq Example - MacOS" + +on: + workflow_dispatch: + inputs: + version: + type: string + required: false + description: "Version of jq to install" + default: "1.6" + download-compressed: + type: boolean + required: false + description: "Download .tar.gz of binary rather than raw binary. Save the tubes." + default: true + force: + type: boolean + required: false + description: "Do not check for existing jq installation before continuing." + default: false + +jobs: + example: + runs-on: macos-latest + steps: + - name: 'Setup jq' + uses: dcarbone/install-jq-action@v1.0.0 + with: + version: '${{ inputs.version }}' + download-compressed: '${{ inputs.download-compressed }}' + force: '${{ inputs.force }}' + + - name: 'Check jq' + run: | + which jq + jq --version diff --git a/.github/workflows/example-windows.yaml b/.github/workflows/example-windows.yaml new file mode 100644 index 0000000..84c8ef3 --- /dev/null +++ b/.github/workflows/example-windows.yaml @@ -0,0 +1,36 @@ +name: "Setup jq Example - Linux" + +on: + workflow_dispatch: + inputs: + version: + type: string + required: false + description: "Version of jq to install" + default: "1.6" + download-compressed: + type: boolean + required: false + description: "Download .tar.gz of binary rather than raw binary. Save the tubes." + default: true + force: + type: boolean + required: false + description: "Do not check for existing jq installation before continuing." + default: false + +jobs: + example: + runs-on: windows-latest + steps: + - name: 'Setup jq' + uses: dcarbone/install-jq-action@v1.0.0 + with: + version: '${{ inputs.version }}' + download-compressed: '${{ inputs.download-compressed }}' + force: '${{ inputs.force }}' + + - name: 'Check jq' + run: | + Get-Command "jq.exe" + jq.exe --version diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml new file mode 100644 index 0000000..59bf3fd --- /dev/null +++ b/.github/workflows/tests.yaml @@ -0,0 +1,145 @@ +name: 'Tests - Setup jq Action' + +on: + workflow_dispatch: + + push: + branches: + - main + paths: + - 'action.yaml' + - '.github/workflows/tests.yaml' + - 'scripts/unixish.sh' + - 'scripts/windowsish.ps1' + + pull_request: + branches: + - main + +jobs: + test-linux: + strategy: + matrix: + image: + - "ubuntu-latest" + - "ubuntu-20.04" + - "ubuntu-22.04" + - "macos-latest" + - "macos-11" + - "macos-12" + - "windows-latest" + - "windows-2022" + - "windows-2019" + download-compressed: + - 'true' + - 'false' + force: + - 'true' + - 'false' + name: "Test Action - (img: ${{ matrix.image }}; dlcmp: ${{ matrix.download-compressed }}; force: ${{ matrix.force }})" + runs-on: ${{ matrix.image }} + steps: + - uses: actions/checkout@v3.1.0 + + - name: Setup jq + id: install-jq + uses: dcarbone/install-jq-action@main + with: + force: '${{ matrix.force }}' + download-compressed: '${{ matrix.download-compressed }}' + + - name: Check jq - Unix-ish + if: runner.os == 'Linux' || runner.os == 'macOS' + run: | + which jq + jq --version + + - name: Check Outputs - Unix-ish + if: runner.os == 'Linux' || runner.os == 'macOS' + shell: bash -e {0} + run: | + _installed='${{ steps.install-jq.outputs.installed }}' + _err= + if [[ '${{ matrix.force }}' == 'true' ]]; then + # enabling "force" must result in an install + if [[ '${{ steps.install-jq.outputs.installed }}' != 'true' ]]; then + echo 'Unexpected value for "installed":' + echo 'Expected: "true"' + echo 'Actual: "${{ steps.install-jq.outputs.installed }}"' + _err=1 + fi + else + if [[ '${{ steps.install-jq.outputs.found }}' == 'true' ]]; then + # if found, must not be installed without force + if [[ '${{ steps.install-jq.outputs.installed }}' != 'false' ]]; then + echo 'Unexpected value for "installed":' + echo 'Expected: "false"' + echo 'Actual: "${{ steps.install-jq.outputs.installed }}"' + _err=1 + fi + else + # if not found, must be installed + if [[ '${{ steps.install-jq.outputs.installed }}' != 'true' ]]; then + echo 'Unexpected value for "installed":' + echo 'Expected: "true"' + echo 'Actual: "${{ steps.install-jq.outputs.installed }}"' + _err=1 + fi + fi + fi + if [ -n "${_err}" ]; then exit 1; fi; + + + - name: Check jq - Windows-ish + if: runner.os == 'Windows' + run: | + Get-Command "jq.exe" + jq.exe --version + + - name: Check Outputs - Windows-ish + if: runner.os == 'Windows' + shell: powershell + run: | + $ErrorActionPreference = 'Stop' + Set-StrictMode -Version Latest + $_installed='${{ steps.install-jq.outputs.installed }}' + $_err = 0 + if ("${{ matrix.force }}" -eq "true") + { + # enabling "force" must result in an install + if ("${{ steps.install-jq.outputs.installed }}" -ne "true") + { + Write-Host "Unexpected value for installed" + Write-Host "Expected: true" + Write-Host "Actual: ${{ steps.install-jq.outputs.installed }}" + $_err=1 + } + } + else + { + if ("${{ steps.install-jq.outputs.found }}" -eq "true") + { + # if found, must not be installed without force + if ("${{ steps.install-jq.outputs.installed }}" -ne "false") + { + Write-Host "Unexpected value for installed" + Write-Host "Expected: false" + Write-Host "Actual: ${{ steps.install-jq.outputs.installed }}" + $_err=1 + } + } + else + { + # if not found, must be installed + if ("${{ steps.install-jq.outputs.installed }}" -ne "true") { + Write-Host "Unexpected value for installed" + Write-Host "Expected: true" + Write-Host "Actual: ${{ steps.install-jq.outputs.installed }}" + $_err=1 + } + } + } + if ("${_err}" -ne 0) + { + exit 1 + } diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c1e1182 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +/.idea +/tmp diff --git a/README.md b/README.md index bcea7a1..39853c0 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,58 @@ # install-jq-action -Multiplatform jq installer action +Multiplatform [jq](https://github.com/stedolan/jq) installer action + +[![Tests - Setup jq Action](https://github.com/dcarbone/install-jq-action/actions/workflows/tests.yaml/badge.svg)](https://github.com/dcarbone/install-jq-action/actions/workflows/tests.yaml) + +This action cannot currently handle MacOS arm64 runners. + +# Index + +1. [Examples](#examples) +2. [Action Source](action.yaml) +3. [Action Inputs](#action-inputs) +4. [Action Outputs](#action-outputs) + +## Examples + +* [linux](./.github/workflows/example-linux.yaml) +* [macos](./.github/workflows/example-macos.yaml) + +## Action Inputs + +#### version +```yaml + version: + required: false + description: "Version of jq to install" + default: "1.6" +``` + +This must be a version with a [corresponding release](https://github.com/stedolan/jq/releases). + +#### force +```yaml + force: + required: false + description: "If 'true', does not check for existing jq installation before continuing." + default: 'false' +``` + +GitHub's own hosted runners come with a version of +[jq pre-installed](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#preinstalled-software). + +Setting this to `true` will install the version you specify into the tool cache, superseding the preinstalled version. +Setting this to true can also help ensure the same version is used across both self-hosted and remote runners. + +## Action Outputs + +#### found +```yaml + found: + description: "If 'true', jq was already found on this runner" +``` + +#### installed +```yaml + installed: + description: "If 'true', jq was installed by this action" +``` diff --git a/action.yaml b/action.yaml new file mode 100644 index 0000000..59b430e --- /dev/null +++ b/action.yaml @@ -0,0 +1,69 @@ +name: Install jq +description: | + Installs a version of jq into the job tool cache using simple shell scripts + +branding: + icon: copy + color: orange + +inputs: + version: + required: false + description: "Version of jq to install" + default: "1.6" + force: + required: false + description: "If 'true', does not check for existing jq installation before continuing." + default: 'false' + +outputs: + found: + description: "If 'true', jq was already found on this runner" + value: "${{ steps.jq-check-unix.outputs.found == 'true' || steps.jq-check-windows.outputs.found == 'true' }}" + installed: + description: "If 'true', jq was installed by this action" + value: "${{ inputs.force == 'true' || steps.jq-check-unix.outputs.found == 'false' || steps.jq-check-windows.outputs.found == 'false' }}" + +runs: + using: composite + steps: + - name: 'Check for jq - Unix-ish' + id: jq-check-unix + if: (runner.os == 'Linux' || runner.os == 'macOS') + shell: bash +e {0} + run: | + _jq_bin="$(which jq)" + if [ -f "${_jq_bin}" ]; then + echo "found=true" >> $GITHUB_OUTPUT + else + echo "found=false" >> $GITHUB_OUTPUT + fi + + - name: 'Install jq - Unix-ish' + if: (runner.os == 'Linux' || runner.os == 'macOS') && (steps.jq-check-unix.outputs.found == 'false' || inputs.force == 'true') + shell: bash + env: + JQ_VERSION: '${{ inputs.version }}' + run: $GITHUB_ACTION_PATH/scripts/unixish.sh + + - name: 'Check for jq - Windows-ish' + id: jq-check-windows + if: runner.os == 'Windows' + shell: powershell + run: | + if (Get-Command "jq.exe" -ErrorAction SilentlyContinue) + { + Add-Content $Env:GITHUB_OUTPUT "found=true" + } + else + { + Add-Content $Env:GITHUB_OUTPUT "found=false" + } + + - name: 'Install jq - Windows-ish' + if: runner.os == 'Windows' && (steps.jq-check-windows.outputs.found == 'false' || inputs.force == 'true') + shell: powershell + env: + DL_COMPRESSED: "${{ inputs.download-compressed == 'true' }}" + JQ_VERSION: '${{ inputs.version }}' + run: '& $Env:GITHUB_ACTION_PATH\scripts\windowsish.ps1' diff --git a/scripts/unixish.sh b/scripts/unixish.sh new file mode 100755 index 0000000..9053206 --- /dev/null +++ b/scripts/unixish.sh @@ -0,0 +1,113 @@ +#!/usr/bin/env bash + +set -e + +echo '::group::Prep' + +# validate input and prepare some vars + +_base_url='https://github.com/stedolan/jq/releases/download' + +_os= +_arch= + +_bin_name= +_dl_name= +_dl_path= +_dl_url= + +case $RUNNER_OS in + Linux) + _os='linux' + ;; + macOS) + _os='osx' + ;; + + *) + echo "Cannot handle OS of type $RUNNER_OS" + echo "Expected one of: [ Linux macOS ]" + exit 1 + ;; +esac + +case $RUNNER_ARCH in + 'X86') + _arch='386' + ;; + 'X64') + _arch='amd64' + ;; + 'ARM') + _arch='arm' + ;; + 'ARM64') + _arch='arm64' + ;; + + *) + echo "Cannot handle arch of type $RUNNER_ARCH" + echo "Expected one of: [ X86 X64 ARM ARM64 ]" + exit 1 + ;; +esac + +# determine binary name + +if [[ "${_os}" == "linux" ]]; then + case "${_arch}" in + '386') + _bin_name="jq-linux32" + ;; + 'amd64') + _bin_name="jq-linux64" + ;; + + *) + echo "Cannot handle \"$RUNNER_ARCH\" architecture for os \"$RUNNER_OS\"" + exit 1 + ;; + esac +else + case "${_arch}" in + 'amd64') + _bin_name="jq-osx-amd64" + ;; + + *) + echo "Cannot handle \"$RUNNER_ARCH\" architecture for os \"$RUNNER_OS\"" + exit 1 + ;; + esac +fi + +_dl_name="${_bin_name}" +_dl_path="$RUNNER_TEMP/${_dl_name}" + +_dl_url="${_base_url}/jq-$JQ_VERSION/${_dl_name}" + +echo '::endgroup::' + +echo '::group::Downloading jq' + +echo "Src: ${_dl_url}" +echo "Dst: ${_dl_path}" + +wget -O- "${_dl_url}" > "${_dl_path}" + +echo '::endgroup::' + +echo '::group::Copying to tool cache' + +echo "Creating tool cache directory $RUNNER_TOOL_CACHE/jq" +mkdir -p "$RUNNER_TOOL_CACHE/jq" + +echo "Installing into tool cache:" +echo "Src: $RUNNER_TEMP/${_bin_name}" +echo "Dst: $RUNNER_TOOL_CACHE/jq/jq" +mv "$RUNNER_TEMP/${_bin_name}" "$RUNNER_TOOL_CACHE/jq/jq" + +echo "Adding $RUNNER_TOOL_CACHE/jq to path..." +echo "$RUNNER_TOOL_CACHE/jq" >> $GITHUB_PATH + +echo '::endgroup::' diff --git a/scripts/windowsish.ps1 b/scripts/windowsish.ps1 new file mode 100644 index 0000000..62112ba --- /dev/null +++ b/scripts/windowsish.ps1 @@ -0,0 +1,58 @@ +$ErrorActionPreference = 'Stop' +Set-StrictMode -Version Latest + +Write-Host "::group::Prep" + +# validate input and prepare some vars + +switch ($Env:RUNNER_ARCH) +{ + "X86" { + $_bin_name = "jq-win32.exe" + } + "X64" { + $_bin_name = "jq-win64.exe" + } + default { + Write-Host "Cannot handle arch of type $Env:RUNNER_ARCH" + Write-Host "Expected one of: [ X86 X64 ]" + exit 1 + } +} + +$_base_url = "https://github.com/stedolan/jq/releases/download" + +$_dl_name = "${_bin_name}" +$_dl_path = "$Env:RUNNER_TEMP\${_dl_name}" + +$_dl_url = "${_base_url}/jq-$Env:JQ_VERSION/${_dl_name}" + +Write-Host "::endgroup::" + +# download artifact + +Write-Host "::group::Downloading jq" + +Write-Host "Src: ${_dl_url}" +Write-Host "Dst: ${_dl_path}" + +Invoke-WebRequest -Uri "${_dl_url}" -OutFile "${_dl_path}" + +Write-Host "::endgroup::" + +# install into tool cache + +Write-Host "::group::Copying to tool cache" + +Write-Host "Creating tool cache directory $Env:RUNNER_TOOL_CACHE\jq\" +New-Item "$Env:RUNNER_TOOL_CACHE\jq\" -ItemType Directory -Force + +Write-Host "Installing into tool cache:" +Write-Host "Src: $Env:RUNNER_TEMP\${_bin_name}" +Write-Host "Dst: $Env:RUNNER_TOOL_CACHE\jq\jq.exe" +Move-Item -Force -LiteralPath "$Env:RUNNER_TEMP\${_bin_name}" -Destination "$Env:RUNNER_TOOL_CACHE\jq\jq.exe" + +Write-Host "Adding $Env:RUNNER_TOOL_CACHE\jq\ to path..." +Add-Content "$Env:GITHUB_PATH" "$Env:RUNNER_TOOL_CACHE\jq\" + +Write-Host "::endgroup::"