diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 1dacb9c..2841b66 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,14 +1,15 @@ ## Summary -Description: +Description: - Tool repo URL: -- Plugin repo URL: +- Plugin repo URL: ## Checklist - This PRs CI tests are green - - test locally with `./test_plugin.sh --file plugins/` + - format with `scripts/format.bash` + - test locally with `scripts/test_plugin.bash --file plugins/` - [ ] Your plugin CI tests are green - _Tip: use the `plugin_test` action from [asdf-actions](https://github.com/asdf-vm/actions) in your plugin CI_ diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml deleted file mode 100644 index 1910fff..0000000 --- a/.github/workflows/format.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: format - -on: - push: - branches: - - master - paths: - - README.md - -jobs: - format_readme: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - name: Setup Node.js - uses: actions/setup-node@v3 - with: - node-version: 18 - - - name: Format README.md - run: npx -y prettier --write README.md - - - name: Commit format of README.md - uses: stefanzweifel/git-auto-commit-action@v4 - with: - commit_message: "chore: format README.md" diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..aa4376f --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,31 @@ +name: lint + +on: + push: + branches: + - master + pull_request: + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Install asdf dependencies + uses: asdf-vm/actions/install@v1 + + - name: lint + run: scripts/lint.bash + + actionlint: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Check workflow files + uses: docker://rhysd/actionlint:1.6.23 + with: + args: -color diff --git a/.github/workflows/semantic-pr.yml b/.github/workflows/semantic-pr.yml index eecb3d0..c135265 100644 --- a/.github/workflows/semantic-pr.yml +++ b/.github/workflows/semantic-pr.yml @@ -1,4 +1,4 @@ -name: lint pull request +name: lint on: pull_request_target: diff --git a/.github/workflows/test-all-plugins.yml b/.github/workflows/test-all-plugins.yml new file mode 100644 index 0000000..0f2641b --- /dev/null +++ b/.github/workflows/test-all-plugins.yml @@ -0,0 +1,21 @@ +name: test + +on: + push: + branches: + - master + paths: + - plugins/* + - README.md + +jobs: + all_plugins: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Check new plugin is registered correctly + run: bash scripts/test_plugin.bash --all diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6f366c5..39b0d30 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,12 +1,12 @@ -name: Test +name: test on: pull_request: paths: - - "plugins/*" + - plugins/* jobs: - check_plugin_registration: + changed_plugins: runs-on: ubuntu-latest steps: - name: Checkout code @@ -15,4 +15,4 @@ jobs: fetch-depth: 0 - name: Check new plugin is registered correctly - run: bash test_plugin.sh --diff origin/master ${{ github.sha }} + run: bash scripts/test_plugin.bash --diff origin/master ${{ github.sha }} diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 0000000..4826a78 --- /dev/null +++ b/.tool-versions @@ -0,0 +1,3 @@ +nodejs 18.14.0 +shellcheck 0.9.0 +shfmt 3.6.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..41d5133 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,36 @@ +# Contributing + +## Contributing a new Plugin + +1. Clone this repo + ```bash + git clone https://github.com/asdf-vm/asdf-plugins + ``` +1. Install repo dependencies + ```bash + asdf install + ``` +1. Add the plugin to the repository `README.md` _Plugin List_ table. +1. Create a file with the shortname you wish to be used by asdf in `plugins/`. The contents should be `repository = `. Eg: + ```bash + printf "repository = https://github.com/asdf-vm/asdf-nodejs.git\n" > plugins/nodejs + ``` +1. Test your code + ```bash + scripts/test_plugin.bash --file plugins/ + ``` +1. Format your code & this README: + ```bash + scripts/format.bash + ``` +1. Create a PR following the instructions in the PR template. + +## Fixing an existing plugin + +If you see a plugin has an incorrect Build status link, please PR a fix to the correct link. + +If you see a plugin which is no longer maintained by the repository owner, please reach out to them on their repo before PRing a removal of the plugin. Sometimes code not actively maintained functions perfectly fine. If you PR a removal, link to the thread showing you attempted to communicate with the owner/author. + +--- + +Thanks for contributing! diff --git a/README.md b/README.md index f923c26..7f398d4 100644 --- a/README.md +++ b/README.md @@ -27,8 +27,12 @@ If you're creating a new plugin consider creating it as part of the [`asdf-commu ## Contributing a new Plugin -- Add the plugin to this `README.md`. -- Create a file with the shortname you wish to be used by asdf in `plugins/`. Then contents should be `repository = `. +- Install repo dependencies: `asdf install` +- Add the plugin to the repository `README.md` _Plugin List_ table. +- Create a file with the shortname you wish to be used by asdf in `plugins/`. The contents should be `repository = `. + - eg: `printf "repository = https://github.com/asdf-vm/asdf-nodejs.git\n" > plugins/nodejs` +- Test your code : `scripts/test_plugin.bash --file plugins/` +- Format your code & this README: `scripts/format.bash` - Create a PR following the instructions in the PR template. ## Security diff --git a/scripts/format.bash b/scripts/format.bash new file mode 100755 index 0000000..3dc3ae7 --- /dev/null +++ b/scripts/format.bash @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# format Shell scripts in scripts/ directory. +shfmt --language-dialect bash --indent 2 --write \ + ./scripts/* + +# format Markdown files. +npx -y prettier --write \ + ./**/*.md diff --git a/scripts/lint.bash b/scripts/lint.bash new file mode 100755 index 0000000..2cdcc48 --- /dev/null +++ b/scripts/lint.bash @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# check format Shell scripts in scripts/ directory. +shfmt --language-dialect bash --indent 2 --diff \ + ./scripts/* + +# check format Markdown files. +npx -y prettier --check \ + ./**/*.md + +# lint for errors in Shell scripts in scripts/ directory. +shellcheck --shell bash --external-sources \ + ./scripts/* diff --git a/test_plugin.sh b/scripts/test_plugin.bash similarity index 81% rename from test_plugin.sh rename to scripts/test_plugin.bash index d4f246c..acd38f6 100755 --- a/test_plugin.sh +++ b/scripts/test_plugin.bash @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# See: ./test_plugin.sh --help +# See: ./scripts/test_plugin.bash --help function fail() { echo "FAIL: $*" >&2 @@ -12,24 +12,25 @@ function badge_svg() { grep -o '(http[^)]*svg[^)]*)' | sed -e 's/(//;s/)//' } -function check_plugin_from_diff() { +function check_plugins_from_diff() { local BASE_REF="$1" # Base commit of main branch. local HEAD_REF="$2" # Latest commit of PR local DIFF_CHANGES DIFF_CHANGES="$(git diff --name-only "${BASE_REF}" "${HEAD_REF}")" - # Assert that the PR diff only includes a change to README and a file under plugins/ + # Assert that the PR diff only includes a change to README and file(s) under plugins/ directory { - test "2" == "$(echo "$DIFF_CHANGES" | wc -l | xargs)" && + test 1 -lt "$(echo "$DIFF_CHANGES" | wc --lines | xargs)" && echo "$DIFF_CHANGES" | grep README.md >/dev/null && echo "$DIFF_CHANGES" | grep plugins/ >/dev/null } || fail "Expected git diff ${REF_RANGE} to only include changes for a single plugin" - local PLUGIN_FILE - PLUGIN_FILE="$(git diff --name-only "${BASE_REF}" "${HEAD_REF}" -- plugins/)" - - check_plugin_from_file "$PLUGIN_FILE" + local PLUGIN_FILES + PLUGIN_FILES="$(git diff --name-only "${BASE_REF}" "${HEAD_REF}" -- plugins/)" + for PLUGIN_FILE in $PLUGIN_FILES; do + check_plugin_from_file "$PLUGIN_FILE" + done } function check_plugin_from_file() { @@ -41,7 +42,7 @@ function check_plugin_from_file() { fail "Expected a plugin file at $PLUGIN_FILE" # Assert that PLUGIN_FILE file ends with new line. - test 'X' == "$(tail -c1 "$PLUGIN_FILE" | tr '\n' 'X')" || + test 'X' == "$(tail --bytes=1 "$PLUGIN_FILE" | tr '\n' 'X')" || fail "Expected $PLUGIN_FILE to end with a new line." # Assert that PLUGIN_FILE has repository key and points to a git repo. @@ -51,20 +52,20 @@ function check_plugin_from_file() { fail "File $PLUGIN_FILE does not specify a repository url" # Assert the plugin repo is reachable. - git ls-remote -q "$PLUGIN_REPO" HEAD >/dev/null || + git ls-remote --quiet "$PLUGIN_REPO" HEAD >/dev/null || fail "Repo is unreachable: $PLUGIN_REPO" local PLUGIN_REPO_NO_GIT - PLUGIN_REPO_NO_GIT="$(echo "$PLUGIN_REPO" | sed -e 's/\.git$//' | tr '/' '\n' | tail -n1)" + PLUGIN_REPO_NO_GIT="$(echo "$PLUGIN_REPO" | sed -e 's/\.git$//' | tr '/' '\n' | tail --lines 1)" local README_LINE - README_LINE="$(git grep -h -C0 "${PLUGIN_REPO_NO_GIT}" -- README.md | head -n 1)" + README_LINE="$(git grep -h --ignore-case -C0 "${PLUGIN_REPO_NO_GIT}" -- README.md | head --lines 1)" # Assert that a new line for plugin was added at README test -n "$README_LINE" || fail "Expected a line at README.md with a link to ${PLUGIN_REPO_NO_GIT}" - BADGE_COLUMN="$(echo "${README_LINE}" | cut -d'|' -f4)" + BADGE_COLUMN="$(echo "${README_LINE}" | cut --delimiter='|' -f4)" BADGE_URL="$(echo "${BADGE_COLUMN}" | badge_svg)" # Assert that the badge has "pass" text in it, indicating the plugin is healthy @@ -104,7 +105,7 @@ if test "--all" == "$*"; then elif test "--diff" == "$1"; then echo "Testing plugin introduced at git diff $2..$3" - check_plugin_from_diff "$2" "$3" + check_plugins_from_diff "$2" "$3" elif test "--file" == "$1"; then check_plugin_from_file "$2"