diff --git a/.editorconfig b/.editorconfig index 1923d41..16bec6a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,8 +1,12 @@ root = true [*] -indent_style = space -indent_size = 2 +indent_style = tab +end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true + +[*.{md,yml,yaml}] +indent_style = space +indent_size = 2 diff --git a/.github/PULL_REQUEST/pull_request_template.md b/.github/PULL_REQUEST/pull_request_template.md index 6d98686..a32de42 100644 --- a/.github/PULL_REQUEST/pull_request_template.md +++ b/.github/PULL_REQUEST/pull_request_template.md @@ -25,7 +25,7 @@ -## Checklist: +## Checklist diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..5ace460 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 514dcbf..49c0e8d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,22 +1,22 @@ name: Build + on: - pull_request: - paths-ignore: - - "**.md" push: - paths-ignore: - - "**.md" + branches: + - main + pull_request: jobs: plugin_test: name: asdf plugin test strategy: matrix: - os: [ubuntu-latest, macos-latest] + os: + - ubuntu-latest + - macos-latest runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4 - name: asdf_plugin_test - uses: asdf-vm/actions/plugin-test@05e0d2ed97b598bfce82fd30daf324ae0c4570e6 # v3 + uses: asdf-vm/actions/plugin-test@v2 with: command: spruce --version diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 28203b4..5c3ffed 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,24 +1,24 @@ name: Lint + on: - pull_request: - paths-ignore: - - "**.md" push: - paths-ignore: - - "**.md" + branches: + - main + pull_request: jobs: lint: - name: Shellcheck and Shell Format runs-on: ubuntu-latest steps: - - name: Checkout code - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4 - - name: asdf_install - uses: asdf-vm/actions/install@05e0d2ed97b598bfce82fd30daf324ae0c4570e6 # v3 - - name: Shellcheck - run: shellcheck -x bin/* -P lib/ - - name: Shell Format - List files to check - run: shfmt -f . - - name: Shell Format - Validate - run: shfmt -d -i 2 -ci . + - uses: actions/checkout@v3 + - uses: asdf-vm/actions/install@v2 + - run: scripts/lint.bash + + actionlint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Check workflow files + uses: docker://rhysd/actionlint:1.6.23 + with: + args: -color diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..454ce7a --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,18 @@ +name: Release + +on: + push: + branches: + - main + +permissions: + contents: write + pull-requests: write + +jobs: + release-please: + runs-on: ubuntu-latest + steps: + - uses: GoogleCloudPlatform/release-please-action@v3 + with: + release-type: simple diff --git a/.github/workflows/semantic-pr.yml b/.github/workflows/semantic-pr.yml new file mode 100644 index 0000000..8b26fa4 --- /dev/null +++ b/.github/workflows/semantic-pr.yml @@ -0,0 +1,18 @@ +name: Lint + +on: + pull_request_target: + types: + - opened + - edited + - synchronize + +jobs: + semantic-pr: + runs-on: ubuntu-latest + steps: + - uses: amannn/action-semantic-pull-request@v5.2.0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + validateSingleCommit: true diff --git a/README.md b/README.md index 2fd4eef..3cd98d5 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@
-# asdf-spruce ![Build](https://github.com/woneill/asdf-spruce/workflows/Build/badge.svg) ![Lint](https://github.com/woneill/asdf-spruce/workflows/Lint/badge.svg) +# asdf-spruce [![Build](https://github.com/woneill/asdf-spruce/actions/workflows/build.yml/badge.svg)](https://github.com/woneill/asdf-spruce/actions/workflows/build.yml) [![Lint](https://github.com/woneill/asdf-spruce/actions/workflows/lint.yml/badge.svg)](https://github.com/woneill/asdf-spruce/actions/workflows/lint.yml) [spruce](https://github.com/geofffranks/spruce) plugin for the [asdf version manager](https://asdf-vm.com). @@ -10,14 +10,12 @@ - [Dependencies](#dependencies) - [Install](#install) -- [Why?](#why) - [Contributing](#contributing) - [License](#license) # Dependencies -- `bash`, `curl`, `tar`: generic POSIX utilities. -- `SOME_ENV_VAR`: set this environment variable in your shell config to load the correct version of tool x. +- `bash`, `curl`, `tar`, and [POSIX utilities](https://pubs.opengroup.org/onlinepubs/9699919799/idx/utilities.html). # Install @@ -56,4 +54,4 @@ Contributions of any kind welcome! See the [contributing guide](contributing.md) # License -See [LICENSE](LICENSE) © [Bill ONeill](https://github.com/woneill/) +See [LICENSE](LICENSE) © [Bill O'Neill](https://github.com/woneill/) diff --git a/bin/download b/bin/download index fdc7e24..324db57 100755 --- a/bin/download +++ b/bin/download @@ -2,13 +2,18 @@ set -euo pipefail -# shellcheck source=../lib/utils.bash -source "$(dirname "$0")/../lib/utils.bash" +current_script_path=${BASH_SOURCE[0]} +plugin_dir=$(dirname "$(dirname "$current_script_path")") + +# shellcheck source=./lib/utils.bash +source "${plugin_dir}/lib/utils.bash" mkdir -p "$ASDF_DOWNLOAD_PATH" -# TODO: Adapt this to proper extension and adapt extracting strategy. +# Adapt this to proper extension and adapt extracting strategy. release_file="$ASDF_DOWNLOAD_PATH/$TOOL_NAME" # Download file to the download directory download_release "$ASDF_INSTALL_VERSION" "$release_file" + +chmod a+x "$release_file" diff --git a/bin/install b/bin/install index 9737a63..6ca759a 100755 --- a/bin/install +++ b/bin/install @@ -5,7 +5,7 @@ set -euo pipefail current_script_path=${BASH_SOURCE[0]} plugin_dir=$(dirname "$(dirname "$current_script_path")") -# shellcheck source=../lib/utils.bash +# shellcheck source=./lib/utils.bash source "${plugin_dir}/lib/utils.bash" install_version "$ASDF_INSTALL_TYPE" "$ASDF_INSTALL_VERSION" "$ASDF_INSTALL_PATH" diff --git a/bin/latest-stable b/bin/latest-stable new file mode 100755 index 0000000..818f26e --- /dev/null +++ b/bin/latest-stable @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +set -euo pipefail + +current_script_path=${BASH_SOURCE[0]} +plugin_dir=$(dirname "$(dirname "$current_script_path")") + +# shellcheck source=./lib/utils.bash +. "${plugin_dir}/lib/utils.bash" + +curl_opts=(-sI) + +if [ -n "${GITHUB_API_TOKEN:-}" ]; then + curl_opts=("${curl_opts[@]}" -H "Authorization: token $GITHUB_API_TOKEN") +fi + +# curl of REPO/releases/latest is expected to be a 302 to another URL +# when no releases redirect_url="REPO/releases" +# when there are releases redirect_url="REPO/releases/tag/v" +redirect_url=$(curl "${curl_opts[@]}" "$GH_REPO/releases/latest" | sed -n -e "s|^location: *||p" | sed -n -e "s|\r||p") +version= +printf "redirect url: %s\n" "$redirect_url" >&2 +if [[ "$redirect_url" == "$GH_REPO/releases" ]]; then + version="$(list_all_versions | sort_versions | tail -n1 | xargs echo)" +else + version="$(printf "%s\n" "$redirect_url" | sed 's|.*/tag/v\{0,1\}||')" +fi + +printf "%s\n" "$version" diff --git a/bin/list-all b/bin/list-all index 943371e..9b8b666 100755 --- a/bin/list-all +++ b/bin/list-all @@ -5,7 +5,7 @@ set -euo pipefail current_script_path=${BASH_SOURCE[0]} plugin_dir=$(dirname "$(dirname "$current_script_path")") -# shellcheck source=../lib/utils.bash +# shellcheck source=./lib/utils.bash source "${plugin_dir}/lib/utils.bash" list_all_versions | sort_versions | xargs echo diff --git a/lib/utils.bash b/lib/utils.bash index 22a58d5..a9c40c1 100644 --- a/lib/utils.bash +++ b/lib/utils.bash @@ -4,69 +4,85 @@ set -euo pipefail GH_REPO="https://github.com/geofffranks/spruce" TOOL_NAME="spruce" -TOOL_TEST="--version" +TOOL_TEST="${TOOL_NAME} --version" fail() { - echo -e "asdf-$TOOL_NAME: $*" - exit 1 + echo -e "asdf-$TOOL_NAME: $*" + exit 1 } curl_opts=(-fsSL) # NOTE: You might want to remove this if spruce is not hosted on GitHub releases. if [ -n "${GITHUB_API_TOKEN:-}" ]; then - curl_opts=("${curl_opts[@]}" -H "Authorization: token $GITHUB_API_TOKEN") + curl_opts=("${curl_opts[@]}" -H "Authorization: token $GITHUB_API_TOKEN") fi sort_versions() { - sed 'h; s/[+-]/./g; s/.p\([[:digit:]]\)/.z\1/; s/$/.z/; G; s/\n/ /' | - LC_ALL=C sort -t. -k 1,1 -k 2,2n -k 3,3n -k 4,4n -k 5,5n | awk '{print $2}' + sed 'h; s/[+-]/./g; s/.p\([[:digit:]]\)/.z\1/; s/$/.z/; G; s/\n/ /' | + LC_ALL=C sort -t. -k 1,1 -k 2,2n -k 3,3n -k 4,4n -k 5,5n | awk '{print $2}' } list_github_tags() { - git ls-remote --tags --refs "$GH_REPO" | - grep -o 'refs/tags/.*' | cut -d/ -f3- | - sed 's/^v//' # NOTE: You might want to adapt this sed to remove non-version strings from tags + git ls-remote --tags --refs "$GH_REPO" | + grep -o 'refs/tags/.*' | cut -d/ -f3- | + sed 's/^v//' # NOTE: You might want to adapt this sed to remove non-version strings from tags } list_all_versions() { - list_github_tags + # TODO: Adapt this. By default we simply list the tag names from GitHub releases. + # Change this function if spruce has other means of determining installable versions. + list_github_tags } download_release() { - local version filename url - version="$1" - filename="$2" - platform="$(uname | tr '[:upper:]' '[:lower:]')" - - # Adapt the release URL convention for spruce - # https://github.com/geofffranks/spruce/releases/download/v1.27.0/spruce-darwin-amd64 - url="$GH_REPO/releases/download/v${version}/${TOOL_NAME}-${platform}-amd64" - - echo "* Downloading $TOOL_NAME release $version..." - curl "${curl_opts[@]}" -o "$filename" -C - "$url" || fail "Could not download $url" - chmod a+x "$filename" + local version filename url + version="$1" + filename="$2" + + local platform architecture + + case "$OSTYPE" in + darwin*) platform="darwin" ;; + linux*) platform="linux" ;; + *) fail "Unsupported platform" ;; + esac + + case "$(uname -m)" in + aarch64* | arm64) architecture="arm64" ;; + x86_64*) architecture="amd64" ;; + *) fail "Unsupported architecture" ;; + esac + + # Adapt the release URL convention for spruce + # https://github.com/geofffranks/spruce/releases/download/v1.27.0/spruce-darwin-amd64 + url="$GH_REPO/releases/download/v${version}/${TOOL_NAME}-${platform}-${architecture}" + + echo "* Downloading $TOOL_NAME release $version for ${platform}-${architecture}..." + curl "${curl_opts[@]}" -o "$filename" -C - "$url" || fail "Could not download $url" } install_version() { - local install_type="$1" - local version="$2" - local install_path="$3" - - if [ "$install_type" != "version" ]; then - fail "asdf-$TOOL_NAME supports release installs only" - fi - - ( - mkdir -p "$install_path"/bin - cp -pr "$ASDF_DOWNLOAD_PATH"/* "$install_path"/bin/ - - test -x "$install_path/bin/$TOOL_NAME" || fail "Expected $install_path/bin/$TOOL_NAME to be executable." - tool_version=$("$install_path"/bin/$TOOL_NAME $TOOL_TEST) && test "${tool_version##*\ }" = "v${version}" || fail "Expected $install_path/bin/$TOOL_NAME to be version v${version} but got ${tool_version##*\ }." - - echo "$TOOL_NAME $version installation was successful!" - ) || ( - rm -rf "$install_path" - fail "An error ocurred while installing $TOOL_NAME $version." - ) + local install_type="$1" + local version="$2" + local install_path="${3%/bin}/bin" + + if [ "$install_type" != "version" ]; then + fail "asdf-$TOOL_NAME supports release installs only" + fi + + ( + mkdir -p "$install_path" + cp -r "$ASDF_DOWNLOAD_PATH"/* "$install_path" + + # TODO: Assert spruce executable exists. + local tool_cmd + tool_cmd="$(echo "$TOOL_TEST" | cut -d' ' -f1)" + test -x "$install_path/$tool_cmd" || fail "Expected $install_path/$tool_cmd to be executable." + + echo "$TOOL_NAME $version installation was successful!" + ) || ( + rm -rf "$install_path" + fail "An error occurred while installing $TOOL_NAME $version." + ) } diff --git a/renovate.json b/renovate.json deleted file mode 100644 index 1b889e9..0000000 --- a/renovate.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": ["local>woneill/.github:renovate-config"] -} diff --git a/scripts/format.bash b/scripts/format.bash new file mode 100755 index 0000000..1a216ea --- /dev/null +++ b/scripts/format.bash @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +shfmt --language-dialect bash --write \ + ./**/* diff --git a/scripts/lint.bash b/scripts/lint.bash new file mode 100755 index 0000000..3451a05 --- /dev/null +++ b/scripts/lint.bash @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +shellcheck --shell=bash --external-sources \ + bin/* --source-path=template/lib/ \ + lib/* \ + scripts/* + +shfmt --language-dialect bash --diff \ + ./**/* diff --git a/version.txt b/version.txt new file mode 100644 index 0000000..e69de29