diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..16bec6a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +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/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..83f93ac --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,27 @@ +--- +name: Bug report +about: Create a report to help us improve +title: "" +labels: bug +assignees: "" +--- + +**Describe the bug** + + + +**Steps to reproduce** + + + +**Expected behavior** + + + +**Screenshots** + + + +**Additional context** + + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..f52b3b9 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,23 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: "" +labels: enhancement +assignees: "" +--- + +**Is your feature request related to a problem? Please describe.** + + + +**Describe the solution you'd like** + + + +**Describe alternatives you've considered** + + + +**Additional context** + + diff --git a/.github/PULL_REQUEST/pull_request_template.md b/.github/PULL_REQUEST/pull_request_template.md new file mode 100644 index 0000000..a32de42 --- /dev/null +++ b/.github/PULL_REQUEST/pull_request_template.md @@ -0,0 +1,34 @@ + + +## Description + + + +## Motivation and Context + + + + +## Types of changes + + + +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to change) + +## Usage examples + + + +## How Has This Been Tested? + + + +## Checklist + + + + +- [ ] I have updated the documentation accordingly. +- [ ] I have added tests to cover my changes. 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/test.yml b/.github/workflows/build.yml similarity index 52% rename from .github/workflows/test.yml rename to .github/workflows/build.yml index 9cc8e13..a63ccb8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/build.yml @@ -1,22 +1,22 @@ ---- -name: Plugin Test +name: Build on: - pull_request: - branches: [master] push: - branches: [master] + 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: asdf-vm/actions/plugin-test@v1 + - name: asdf_plugin_test + uses: asdf-vm/actions/plugin-test@v2 with: command: kconf version - - diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..e2bf746 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,32 @@ +name: Lint + +on: + push: + branches: + - main + pull_request: + +jobs: + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v3 + - uses: asdf-vm/actions/install@v2 + - uses: pre-commit/action@v3.0.0 + + lint: + runs-on: ubuntu-latest + steps: + - 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..c32b2ae --- /dev/null +++ b/.github/workflows/semantic-pr.yml @@ -0,0 +1,18 @@ +name: Semantic PR + +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/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..713cefd --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,28 @@ +--- +# installation: `pre-commit install` +default_install_hook_types: + - pre-commit + - commit-msg +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: check-merge-conflict + - id: end-of-file-fixer + - id: trailing-whitespace + args: + - "--markdown-linebreak-ext=md" + - repo: https://github.com/Yelp/detect-secrets + rev: v1.4.0 + hooks: + - id: detect-secrets + - repo: https://github.com/semgrep/semgrep + rev: v1.48.0 + hooks: + - id: semgrep-ci + - repo: https://github.com/jumanjihouse/pre-commit-hooks + rev: 3.0.0 + hooks: + - id: script-must-not-have-extension + - id: shellcheck + - id: shfmt diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 0000000..5484d6e --- /dev/null +++ b/.tool-versions @@ -0,0 +1,3 @@ +shellcheck 0.9.0 +shfmt 3.6.0 +pre-commit 3.5.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..7ea6bae --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,11 @@ +# Contributing + +Testing Locally: + +```shell +asdf plugin test [--asdf-tool-version ] [--asdf-plugin-gitref ] [test-command*] + +asdf plugin test kconf https://github.com/particledecay/asdf-kconf "kconf version" +``` + +Tests are automatically run in GitHub Actions on push and PR. diff --git a/LICENSE b/LICENSE index 63b4b68..bb54ca2 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) [year] [fullname] +Copyright (c) 2023 Joey Espinosa Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file +SOFTWARE. diff --git a/README.md b/README.md index 46cc39c..4e3c01f 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,57 @@ -# asdf-kconf [![Plugin Test](https://github.com/particledecay/asdf-kconf/workflows/Plugin%20Test/badge.svg)](https://github.com/particledecay/asdf-kconf) -[asdf version manager](https://github.com/asdf-vm/asdf) plugin for [kconf](https://github.com/particledecay/kconf) Kubernetes configuration manager +
-## Install -```bash -asdf plugin-add kconf https://github.com/particledecay/asdf-kconf.git +# asdf-kconf [![Build](https://github.com/particledecay/asdf-kconf/actions/workflows/build.yml/badge.svg)](https://github.com/particledecay/asdf-kconf/actions/workflows/build.yml) [![Lint](https://github.com/particledecay/asdf-kconf/actions/workflows/lint.yml/badge.svg)](https://github.com/particledecay/asdf-kconf/actions/workflows/lint.yml) + +[kconf](https://github.com/particledecay/kconf) plugin for the [asdf version manager](https://asdf-vm.com). + +
+ +# Contents + +- [Dependencies](#dependencies) +- [Install](#install) +- [Contributing](#contributing) +- [License](#license) + +# Dependencies + +- `bash`, `curl`, `tar`, and [POSIX utilities](https://pubs.opengroup.org/onlinepubs/9699919799/idx/utilities.html). + +# Install + +Plugin: + +```shell +asdf plugin add kconf +# or +asdf plugin add kconf https://github.com/particledecay/asdf-kconf.git +``` + +kconf: + +```shell +# Show all installable versions +asdf list-all kconf + +# Install specific version +asdf install kconf latest + +# Set a version globally (on your ~/.tool-versions file) +asdf global kconf latest + +# Now kconf commands are available +kconf version ``` -## Use -Check out the [asdf](https://github.com/asdf-vm/asdf) readme for instructions on how to install and manage versions of kconf. +Check [asdf](https://github.com/asdf-vm/asdf) readme for more instructions on how to +install & manage versions. + +# Contributing + +Contributions of any kind welcome! See the [contributing guide](contributing.md). + +[Thanks goes to these contributors](https://github.com/particledecay/asdf-kconf/graphs/contributors)! + +# License + +See [LICENSE](LICENSE) © [Joey Espinosa](https://github.com/particledecay/) diff --git a/bin/download b/bin/download index b652cd1..68e4880 100755 --- a/bin/download +++ b/bin/download @@ -1,59 +1,22 @@ #!/usr/bin/env bash -set \ - -o errexit \ - -o nounset \ - -o pipefail - -# required environment variables -: ${ASDF_INSTALL_VERSION?} -: ${ASDF_DOWNLOAD_PATH?} - -readonly repository="particledecay/kconf" -readonly toolname="kconf" - -# rate limit support with a proper token -CURL="curl -s" -if [ -n "${OAUTH_TOKEN:-}" ] -then - CURL="$CURL -H 'Authorization: token $OAUTH_TOKEN'" -fi - -download() { - local -r os=$(get_os) - local -r arch=$(get_arch) - local -r filename="${toolname}-${os}-${arch}-${ASDF_INSTALL_VERSION}.tar.gz" - local -r download_url="$(get_download_url $filename)" - - echo "Downloading ${toolname} version ${ASDF_INSTALL_VERSION} from ${download_url}" - if $CURL -fsL "${download_url}" -o "${ASDF_DOWNLOAD_PATH}/${filename}" - then - echo "Successfully downloaded ${filename}" - exit 0 - else - echo "Failed to download ${filename}" - exit 1 - fi -} - -# get the OS family name -get_os() { - uname | tr '[:upper:]' '[:lower:]' -} - -# get the cpu architecture -get_arch() { - uname -m -} - -# return the full URL to the download -get_download_url() { - local -r filename=$1 - - local -r os=$(get_os) - local -r arch=$(get_arch) - - echo "https://github.com/$repository/releases/download/v${ASDF_INSTALL_VERSION}/$filename" -} - -download +set -euo pipefail + +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" + +release_file="$ASDF_DOWNLOAD_PATH/$TOOL_NAME-$(get_os)-$(get_arch)-$ASDF_INSTALL_VERSION.tar.gz" + +# Download tar.gz file to the download directory +download_release "$ASDF_INSTALL_VERSION" "$release_file" + +# Extract contents of tar.gz file into the download directory +tar -xzf "$release_file" -C "$ASDF_DOWNLOAD_PATH" "$TOOL_NAME" || fail "Could not extract $release_file" + +# Remove the tar.gz file since we don't need to keep it +rm "$release_file" diff --git a/bin/install b/bin/install index cbcd67c..6ca759a 100755 --- a/bin/install +++ b/bin/install @@ -1,44 +1,11 @@ #!/usr/bin/env bash -set \ - -o errexit \ - -o nounset \ - -o pipefail +set -euo pipefail -# required environment variables -: ${ASDF_INSTALL_TYPE?} -: ${ASDF_INSTALL_VERSION?} -: ${ASDF_INSTALL_PATH?} -: ${ASDF_DOWNLOAD_PATH?} +current_script_path=${BASH_SOURCE[0]} +plugin_dir=$(dirname "$(dirname "$current_script_path")") -readonly repository="particledecay/kconf" -readonly toolname="kconf" +# shellcheck source=./lib/utils.bash +source "${plugin_dir}/lib/utils.bash" -install() { - local -r os=$(get_os) - local -r arch=$(get_arch) - local -r filename="${toolname}-${os}-${arch}-${ASDF_INSTALL_VERSION}.tar.gz" - local -r download_pkg="${ASDF_DOWNLOAD_PATH}/${filename}" - - echo "Extracting ${toolname} from tar archive" - [ ! -d "${ASDF_INSTALL_PATH}/bin" ] && mkdir -p "${ASDF_INSTALL_PATH}/bin" - tar xf "$download_pkg" -C "${ASDF_INSTALL_PATH}/bin" "$toolname" 2>/dev/null - if [ $? -eq 0 ] - then - echo "Successfully installed ${toolname} ${ASDF_INSTALL_VERSION}" - exit 0 - else - echo "Failed to install ${toolname} ${ASDF_INSTALL_VERSION}" - exit 1 - fi -} - -get_os() { - uname | tr '[:upper:]' '[:lower:]' -} - -get_arch() { - uname -m -} - -install +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 f55a264..9b8b666 100755 --- a/bin/list-all +++ b/bin/list-all @@ -1,21 +1,11 @@ #!/usr/bin/env bash -set \ - -o errexit \ - -o nounset \ - -o pipefail +set -euo pipefail -readonly repository="particledecay/kconf" +current_script_path=${BASH_SOURCE[0]} +plugin_dir=$(dirname "$(dirname "$current_script_path")") -CURL="curl -s" -if [ -n "${OAUTH_TOKEN:-}" ]; -then - CURL="$CURL -H 'Authorization: token $OAUTH_TOKEN'" -fi +# shellcheck source=./lib/utils.bash +source "${plugin_dir}/lib/utils.bash" -function sort_versions() { - LC_ALL=C sort -t. -k 1,1 -k 2,2n -k 3,3n -} - -versions=$($CURL -fsL "https://api.github.com/repos/$repository/releases" | grep tag_name | sed 's/"tag_name": //g;s/"//g;s/,//g;s/v//g;/1.6.0/q') -echo "$versions" | sort_versions | xargs +list_all_versions | sort_versions | xargs echo diff --git a/lib/utils.bash b/lib/utils.bash new file mode 100644 index 0000000..fa461e7 --- /dev/null +++ b/lib/utils.bash @@ -0,0 +1,91 @@ +#!/usr/bin/env bash + +set -euo pipefail + +GH_REPO="https://github.com/particledecay/kconf" +TOOL_NAME="kconf" +TOOL_TEST="kconf version" + +fail() { + echo -e "asdf-$TOOL_NAME: $*" + exit 1 +} + +curl_opts=(-fsSL) + +if [ -n "${GITHUB_API_TOKEN:-}" ]; then + 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}' +} + +list_github_tags() { + git ls-remote --tags --refs "$GH_REPO" | + grep -o 'refs/tags/.*' | cut -d/ -f3- | + sed 's/^v//' +} + +list_all_versions() { + list_github_tags +} + +download_release() { + local version filename url + version="$1" + filename="$2" + + url="$GH_REPO/releases/download/v${version}/$TOOL_NAME-$(get_os)-$(get_arch)-${version}.tar.gz" + + echo "* Downloading $TOOL_NAME release $version..." + 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%/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" + + 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." + ) +} + +get_os() { + local os + os="$(uname | tr '[:upper:]' '[:lower:]')" + + echo "$os" +} + +get_arch() { + local arch + arch="$(uname -m)" + + case "$arch" in + i?86 | x86) + arch="386" + ;; + aarch64 | arm64) + arch="arm64" + ;; + esac + + echo "$arch" +} 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 \ + ./**/*