diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..526661e --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,43 @@ +name: Release + +on: + push: + branches: [main] + +env: + GH_TOKEN: ${{ github.token }} + +jobs: + Release: + name: Release + permissions: write-all + runs-on: [ubuntu-latest] + steps: + - uses: actions/checkout@v4 + + - id: get-version + uses: robzr/sver@v1 + with: + command: json "$(./asdf-sync -V)" + + - id: is-existing-release + uses: robzr/sver@v1 + with: + command: filter '${{ fromJSON(steps.get-version.outputs.output).version }}' + input-command: gh release list --json tagName --jq '.[] | .tagName' + + - env: + MAJOR: ${{ fromJSON(steps.get-version.outputs.output).major }} + MINOR: ${{ fromJSON(steps.get-version.outputs.output).minor }} + VERSION: v${{ fromJSON(steps.get-version.outputs.output).version }} + if: steps.is-existing-release.outputs.output != '' + name: Create New Release + run: | + gh release \ + create "$VERSION" \ + --generate-notes \ + --latest \ + sver + git tag -f "v${MAJOR}" + git tag -f "v${MAJOR}.${MINOR}" + git push -f --tags diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index e410d54..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,18 +0,0 @@ -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@v4 - with: - release-type: simple diff --git a/.github/workflows/semantic-pr.yml b/.github/workflows/semantic-pr.yml deleted file mode 100644 index e6b3c9d..0000000 --- a/.github/workflows/semantic-pr.yml +++ /dev/null @@ -1,18 +0,0 @@ -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.4.0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - validateSingleCommit: true diff --git a/asdf-sync b/asdf-sync index 9c62adc..92831c3 100755 --- a/asdf-sync +++ b/asdf-sync @@ -1,8 +1,9 @@ #!/usr/bin/env bash +# shellcheck disable=SC1008,SC2015,SC2096 # # asdf-sync by Rob Zwissler (@robzr) 4/5/2024 https://github.com/robzr/asdf-sync -VERSION=v0.4.2 +VERSION=v0.4.3 SVER_RUN=false #### BEGIN SVER @@ -77,18 +78,18 @@ _sver_complete_function() { "${COMP_WORDS[1]}" || true) elif [ "$COMP_CWORD" = 2 ]; then case "${COMP_WORDS[1]}" in - bump) - # shellcheck disable=SC2046 - read -ra COMPREPLY <<<$(compgen -W "major minor patch" "${COMP_WORDS[2]}" || true) - ;; - get) - # shellcheck disable=SC2046 - read -ra COMPREPLY <<<$(compgen -W \ - "build_metadata major minor patch prerelease" "${COMP_WORDS[2]}" || true) - ;; - *) - COMPREPLY=() - ;; + bump) + # shellcheck disable=SC2046 + read -ra COMPREPLY <<<$(compgen -W "major minor patch" "${COMP_WORDS[2]}" || true) + ;; + get) + # shellcheck disable=SC2046 + read -ra COMPREPLY <<<$(compgen -W \ + "build_metadata major minor patch prerelease" "${COMP_WORDS[2]}" || true) + ;; + *) + COMPREPLY=() + ;; esac fi } @@ -677,20 +678,20 @@ if [ "${SVER_RUN:-true}" = true ]; then fi fi case "$command" in - bump_* | constraint | get_* | greater_than | json | less_than | yaml) - if ! sver_validate "$1"; then - echo "Error: Invalid semver specified (${1})." >&2 - exit 1 - fi - ;; + bump_* | constraint | get_* | greater_than | json | less_than | yaml) + if ! sver_validate "$1"; then + echo "Error: Invalid semver specified (${1})." >&2 + exit 1 + fi + ;; esac case "$command" in - equals | greater_than | less_than) - if ! sver_validate -s "$2"; then - echo "Error: Invalid semver substring specified (${2})." >&2 - exit 1 - fi - ;; + equals | greater_than | less_than) + if ! sver_validate -s "$2"; then + echo "Error: Invalid semver substring specified (${2})." >&2 + exit 1 + fi + ;; esac status=0 @@ -708,32 +709,31 @@ log() { local echo_arg local min_verbosity=$1 shift - if [ "$1" = "-n" ] ; then + if [ "$1" = "-n" ]; then echo_arg="-n" shift fi - if [ "$VERBOSITY" -ge "$min_verbosity" ] ; then + if [ "$VERBOSITY" -ge "$min_verbosity" ]; then echo $echo_arg "$@" fi } process_tool_versions() { - local accum broke char comment constraint i ignore inside_quote keys + local broke char comment constraint i ignore inside_quote keys local existing_url existing_ref found plugins_tool plugins_url plugins_ref local sync_url sync_ref regex tmp run_tools tool version values versions words declare -a keys run_tools values versions words declare -a plugins_tool plugins_url plugins_ref - local verbosity="$1" shift run_tools=() - while [ -n "$1" ] ; do + while [ -n "$1" ]; do run_tools+=("$1") shift done regex='^([^ ]*) *([^ ]*) *([^ ]*)' - while IFS="$'\r'" read -r line ; do - if [[ "$line" =~ $regex ]] ; then + while IFS=$'\r' read -r line; do + if [[ "$line" =~ $regex ]]; then plugins_tool+=("${BASH_REMATCH[1]}") plugins_url+=("${BASH_REMATCH[2]}") plugins_ref+=("${BASH_REMATCH[3]}") @@ -741,17 +741,17 @@ process_tool_versions() { done <<<"$(asdf plugin list --urls --refs)" # syntax of tool-versions is: " [ ...] [# ]" - while IFS="$'\n'" read -r line ; do + while IFS=$'\n' read -r line; do comment=${line#*#} - if [ "$comment" = "$line" ] ; then + if [ "$comment" = "$line" ]; then comment= fi line=${line%%#*} tool=${line%% *} - if [ "${#run_tools[@]}" -gt 0 ] ; then + if [ "${#run_tools[@]}" -gt 0 ]; then found=false - for tmp in "${run_tools[@]}" ; do - if [ "$tmp" = "$tool" ] ; then + for tmp in "${run_tools[@]}"; do + if [ "$tmp" = "$tool" ]; then found=true fi done @@ -763,17 +763,17 @@ process_tool_versions() { tmp=${tmp%#*} versions=() - while [ -n "$tmp" ] ; do + while [ -n "$tmp" ]; do version=${tmp%% *} - versions+=($version) + versions+=("$version") tmp=${tmp#* } - if [ "$tmp" = "$version" ] ; then + if [ "$tmp" = "$version" ]; then tmp= fi done - log 6 " - versions=${version[@]}" + log 6 " - versions=${version[*]}" - if [ -z "$tool" ] || [[ "${#versions[@]}" -lt 1 ]] ; then + if [ -z "$tool" ] || [[ "${#versions[@]}" -lt 1 ]]; then continue fi @@ -781,29 +781,29 @@ process_tool_versions() { inside_quote=false words=() comment=${comment## } - for (( i=0 ; i <= ${#comment} && ${#comment} > 0 ; i++ )) ; do + for ((i = 0; i <= ${#comment} && ${#comment} > 0; i++)); do char=${comment:i:1} - if [ -z "$char" ] ; then - words+=("$tmp") - elif [ "$char" = ' ' ] ; then - if $inside_quote ; then + if [ -z "$char" ]; then + words+=("$tmp") + elif [ "$char" = ' ' ]; then + if $inside_quote; then tmp+="$char" else - ! [ -n "$tmp" ] || words+=("$tmp") + [ -z "$tmp" ] || words+=("$tmp") tmp= fi - elif [ "$char" = '"' ] ; then + elif [ "$char" = '"' ]; then $inside_quote && inside_quote=false || inside_quote=true tmp+="$char" - else + else tmp+="$char" fi done keys=() values=() - for word in "${words[@]}" ; do - if [[ "$word" =~ ^(sync-[^=]+)=(.*)$ ]] ; then + for word in "${words[@]}"; do + if [[ "$word" =~ ^(sync-[^=]+)=(.*)$ ]]; then keys+=("${BASH_REMATCH[1]}") tmp="${BASH_REMATCH[2]#\"}" tmp=${tmp%\"} @@ -816,32 +816,32 @@ process_tool_versions() { ignore=false sync_ref= sync_url= - for (( i = 0 ; i < ${#keys[@]} ; i++ )) ; do + for ((i = 0; i < ${#keys[@]}; i++)); do log 5 "keys[${i}]=${keys[i]} values[${i}]=${values[i]}" - if [ "${keys[i]}" = 'sync-constraint' ] || [ "${keys[i]}" = 'sync-constraints' ] ; then + if [ "${keys[i]}" = 'sync-constraint' ] || [ "${keys[i]}" = 'sync-constraints' ]; then constraint="${values[i]}" - elif [ "${keys[i]}" = 'sync-ignore' ] ; then - if [ "${values[i]}" = 'true' ] ; then + elif [ "${keys[i]}" = 'sync-ignore' ]; then + if [ "${values[i]}" = 'true' ]; then ignore=true fi - elif [ "${keys[i]}" = 'sync-ref' ] ; then + elif [ "${keys[i]}" = 'sync-ref' ]; then sync_ref="${values[i]}" - elif [ "${keys[i]}" = 'sync-url' ] ; then + elif [ "${keys[i]}" = 'sync-url' ]; then sync_url="${values[i]}" - elif [ "${keys[i]/sync-*/sync}" = 'sync' ] ; then + elif [ "${keys[i]/sync-*/sync}" = 'sync' ]; then log 1 "Warning: unknown sync key found (${keys[i]}) on tool ${tool}, skipping." broke=true fi done - if $broke ; then + if $broke; then continue fi existing_ref= existing_url= - for (( i = 0 ; i < ${#plugins_tool[@]} ; i++ )) ; do + for ((i = 0; i < ${#plugins_tool[@]}; i++)); do log 6 "(${tool})[${i}] plugins_url=${plugins_url[i]} plugins_ref=${plugins_ref[i]}" - if [ "${plugins_tool[i]}" = "$tool" ] ; then + if [ "${plugins_tool[i]}" = "$tool" ]; then existing_ref=${plugins_ref[i]} existing_url=${plugins_url[i]} break @@ -849,15 +849,15 @@ process_tool_versions() { done log 5 "tool=${tool} existing_url=${existing_url} existing_ref=${existing_ref} sync_url=${sync_url} sync_ref=${sync_ref}" - if [ -n "$sync_url" ] ; then - if [ -z "$existing_url" ] ; then + if [ -n "$sync_url" ]; then + if [ -z "$existing_url" ]; then log 1 "${tool} plugin is not installed, adding using sync-url ${sync_url}" asdf plugin add "$tool" "$sync_url" existing_ref=$(asdf plugin list --urls --refs | sed -n "/^${tool} */s/[^ ]* *[^ ]* *\([^ ]*\) .*/\1/p") - elif [ "$existing_url" = "$sync_url" ] ; then + elif [ "$existing_url" = "$sync_url" ]; then log 2 "${tool} plugin is already installed with sync_url" else - if "$FORCE" ; then + if "$FORCE"; then log 1 "${tool} plugin installed with different URL from sync-url, overriding" asdf plugin remove "$tool" asdf plugin add "$tool" "$sync_url" @@ -865,7 +865,7 @@ process_tool_versions() { log 1 "${tool} plugin installed with different URL from sync-url, ignoring (use -f to force install)" fi fi - elif [ -z "${existing_url}" ] ; then + elif [ -z "${existing_url}" ]; then log 1 "${tool} plugin is not installing, adding" asdf plugin add "$tool" existing_ref=$(asdf plugin list --urls --refs | sed -n "/^${tool} */s/[^ ]* *[^ ]* *\([^ ]*\) .*/\1/p") @@ -873,11 +873,11 @@ process_tool_versions() { log 1 "${tool} plugin is already installed" fi - if [ -n "$sync_ref" ] ; then - if [ -z "$existing_ref" ] ; then + if [ -n "$sync_ref" ]; then + if [ -z "$existing_ref" ]; then log 1 "${tool} plugin is not installed, not in registry, and no sync-url was specified, ignoring sync-ref" else - if [ "$existing_ref" = "$sync_ref" ] ; then + if [ "$existing_ref" = "$sync_ref" ]; then log 1 "${tool} plugin is already installed with same ref as sync-ref" else log 1 "${tool} plugin is already installed with different ref from sync-ref, updating and switching" @@ -886,19 +886,19 @@ process_tool_versions() { fi fi - if ! $ignore && [ -n "$constraint" ] ; then + if ! $ignore && [ -n "$constraint" ]; then log 1 -n "${tool} checking sync-constraint \"${constraint}\" " version=$(asdf list all "${tool}" | sver_max "${constraint}") - if [ "$version" != "${versions[0]}" ] ; then + if [ "$version" != "${versions[0]}" ]; then log 1 "- found new version, upgrading ${versions[0]} -> ${version}" tmp=$(mktemp) - sed "s/^\( *${tool} *\)[^ ][^ ]*\(.*\)/\1${version}\2/" "$TOOL_VERSIONS_FILE" > "$tmp" - mv "$tmp" "$TOOL_VERSIONS_FILE" + sed "s/^\( *${tool} *\)[^ ][^ ]*\(.*\)/\1${version}\2/" "$TOOL_VERSIONS_FILE" >"$tmp" + mv "$tmp" "$TOOL_VERSIONS_FILE" else log 1 "- version up to date" fi fi - done < "$TOOL_VERSIONS_FILE" + done <<<"$(cat "$TOOL_VERSIONS_FILE")" } print_help() { @@ -935,47 +935,46 @@ print_help() { } FORCE=false -MY_NAME="asdf sync" declare -a TOOL TOOL_VERSIONS_FILE=${ASDF_DEFAULT_TOOL_VERSIONS_FILENAME:-.tool-versions} VERBOSITY=${ASDF_SYNC_VERBOSITY:-1} while getopts "fhqvV" arg; do case "$arg" in - f) - FORCE=true - ;; - h) - print_help - exit 0 - ;; - q) - VERBOSITY=0 - ;; - v) - VERBOSITY=2 - ;; - V) - echo "$VERSION" - exit 0 - ;; - *) - print_help - exit 1 - ;; + f) + FORCE=true + ;; + h) + print_help + exit 0 + ;; + q) + VERBOSITY=0 + ;; + v) + VERBOSITY=2 + ;; + V) + echo "$VERSION" + exit 0 + ;; + *) + print_help + exit 1 + ;; esac done -shift $((OPTIND-1)) +shift $((OPTIND - 1)) TOOL=("${@}") -if [ -f "$TOOL_VERSIONS_FILE" ] ; then +if [ -f "$TOOL_VERSIONS_FILE" ]; then process_tool_versions "$VERBOSITY" "${TOOL[@]}" else - if "$FORCE" ; then + if "$FORCE"; then exit 0 else - if [ "$VERBOSITY" -gt 0 ] ; then + if [ "$VERBOSITY" -gt 0 ]; then echo "Error: no $TOOL_VERSIONS_FILE found" fi exit 1 diff --git a/lib/utils.bash b/lib/utils.bash index 154e89c..1c03371 100644 --- a/lib/utils.bash +++ b/lib/utils.bash @@ -8,67 +8,67 @@ TOOL_NAME="sync" TOOL_TEST="asdf-sync --help" 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 sync 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() { - # TODO: Adapt this. By default we simply list the tag names from GitHub releases. - # Change this function if sync has other means of determining installable versions. - list_github_tags + # TODO: Adapt this. By default we simply list the tag names from GitHub releases. + # Change this function if sync has other means of determining installable versions. + list_github_tags } download_release() { - local version filename url - version="$1" - filename="$2" + local version filename url + version="$1" + filename="$2" - # TODO: Adapt the release URL convention for sync - url="$GH_REPO/archive/v${version}.tar.gz" + # TODO: Adapt the release URL convention for sync + url="$GH_REPO/archive/v${version}.tar.gz" - echo "* Downloading $TOOL_NAME release $version..." - curl "${curl_opts[@]}" -o "$filename" -C - "$url" || fail "Could not download $url" + 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" - - # TODO: Assert sync 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." - ) + 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 sync 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/scripts/format.bash b/scripts/format.bash index 1a216ea..f846281 100755 --- a/scripts/format.bash +++ b/scripts/format.bash @@ -1,4 +1,4 @@ #!/usr/bin/env bash shfmt --language-dialect bash --write \ - ./**/* + ./**/* diff --git a/scripts/lint.bash b/scripts/lint.bash index 3451a05..73e478a 100755 --- a/scripts/lint.bash +++ b/scripts/lint.bash @@ -1,9 +1,11 @@ #!/usr/bin/env bash shellcheck --shell=bash --external-sources \ - bin/* --source-path=template/lib/ \ - lib/* \ - scripts/* + bin/* --source-path=template/lib/ \ + lib/*.bash \ + lib/commands/*.bash \ + scripts/* \ + asdf-sync -shfmt --language-dialect bash --diff \ - ./**/* +shfmt --language-dialect bash -i 2 --diff \ + asdf-sync ./**/*