diff --git a/.build/README.j2.md b/.build/README.j2.md index ae43b52..50d2833 100644 --- a/.build/README.j2.md +++ b/.build/README.j2.md @@ -4,6 +4,8 @@ hyakvnc -- A tool for launching VNC sessions on Hyak. `hyakvnc` is a command-line tool that makes it easy to start a graphical [VNC](https://en.wikipedia.org/wiki/Virtual_Network_Computing) session on the University of Washington [Hyak](https://hyak.uw.edu/) cluster, allowing you to interact with the system in a point-and-click environment, with support for graphical applications such as [Freesurfer](https://surfer.nmr.mgh.harvard.edu/). `hyakvnc` sessions run in [Apptainer](https://apptainer.org) containers, which provide reproducible environments that can run anywhere and be shared with other researchers. +*If you're already familiar with Hyak and VNC and you just want to install `hyakvnc` immediately, you can skip to the [quick install](#quick-install) section.* + ## Prerequisites Before running `hyakvnc`, you'll need the following: @@ -78,7 +80,7 @@ ssh your-uw-netid@klone.hyak.uw.edu After you've connected to the login node, you can download and install `hyakvnc` by running the following command. Copy and paste it into the terminal window where you are connected to the login node and press enter: ```bash -curl -o ~/.local/bin/hyakvnc --create-dirs -fsSL https://raw.githubusercontent.com/{{github_repository}}/{{github_ref_name}}/hyakvnc && chmod +x ~/.local/bin/hyakvnc && [[ ":${PATH}:" != *":$HOME/.local/bin:"* ]] && export PATH="$HOME/.local/bin:$PATH" && [-n "${ZSH_VERSION:-}" ] && rehash +eval "$(curl -fsSL https://raw.githubusercontent.com//{{github_repository}}/{{github_ref_name}}/install.sh)" ``` This will download and install `hyakvnc` to your `~/.local/bin` directory and add it to your `$PATH` so you can run it by typing `hyakvnc` into the terminal window. @@ -88,7 +90,7 @@ This will download and install `hyakvnc` to your `~/.local/bin` directory and ad In a terminal window connected to a login node, enter this command to clone the repository and navigate into the repository directory: ```bash -git clone https://github.com/{{github_repository}} && cd hyakvnc +git clone --depth 1 --single-branch https://github.com/{{github_repository}} && cd hyakvnc ``` Then, run the following command to install `hyakvnc`: diff --git a/.build/install.j2.sh b/.build/install.j2.sh new file mode 100755 index 0000000..09d4a74 --- /dev/null +++ b/.build/install.j2.sh @@ -0,0 +1,70 @@ +#!/bin/sh + +# install.sh is generated from .build/install.j2.sh. Do not edit it directly. +# This script is intended to be sourced from the current shell. +# It will clone the hyakvnc repository to ~/.hyakvnc/hyakvnc and create a symlink in it to ~/.local/bin/hyakvnc. +# These locations can be changed by setting the following environment variables: +# - HYAKVNC_DIR: Local directory to store application data (default: `$HOME/.hyakvnc`) +# - HYAKVNC_REPO_DIR: Local directory to store git repository (default: `$HYAKVNC_DIR/hyakvnc`) +# - HYAKVNC_REPO_URL: URL of the git repository to clone (default: {{j2_hyakvnc_repo_url}}) +# - BIN_INSTALL_DIR: Local directory to store executable (default: `$HOME/.local/bin`) + +_add_hyakvnc_to_path() { + [ -z "${_UNEXPANDED_BIN_INSTALL_DIR:-}" ] || [ -z "${_BIN_INSTALL_DIR:-}" ] && return 1 + case "${PATH:-}" in + *"${_BIN_INSTALL_DIR}"*) ;; + *) + if [ -n "${BASH_VERSION:-}" ]; then + echo "export PATH=\"${_UNEXPANDED_BIN_INSTALL_DIR}:\$PATH\"" >>"${HOME:-}/.bashrc" + echo "Added hyakvnc to PATH in ${HOME:-}/.bashrc" 2>&1 + export PATH="${_BIN_INSTALL_DIR}:${PATH:-}" + elif [ -n "${ZSH_VERSION:-}" ]; then + echo "export PATH=\"${_UNEXPANDED_BIN_INSTALL_DIR}:\$PATH\"" >>"${ZDOTDIR:-${HOME:-}}/.zshrc" && echo "Added hyakvnc to PATH in ${ZDOTDIR:-${HOME}}/.zshrc" 2>&1 + export PATH="${_BIN_INSTALL_DIR}:${PATH:-}" + rehash 2>/dev/null || true + elif [ "${0:-}" = "dash" ] || [ "${0:-}" = "sh" ]; then + echo "export PATH=\"${_UNEXPANDED_BIN_INSTALL_DIR}:\$PATH\"" >>"${HOME}/.profile" && echo "Added hyakvnc to PATH in ${HOME}/.profile" 2>&1 + export PATH="${_BIN_INSTALL_DIR}:${PATH:-}" + else + echo "Could not add hyakvnc to PATH." 2>&1 + return 1 + fi + ;; + esac +} + +_install_hyakvnc() { + _HYAKVNC_DIR="${_HYAKVNC_DIR:-${HOME}/.hyakvnc}" # %% Local directory to store application data (default: `$HOME/.hyakvnc`) + _HYAKVNC_REPO_DIR="${_HYAKVNC_REPO_DIR:-${_HYAKVNC_DIR}/hyakvnc}" # Local directory to store git repository (default: `$HYAKVNC_DIR/hyakvnc`) + _HYAKVNC_REPO_URL="${_HYAKVNC_REPO_URL:-"{{j2_hyakvnc_repo_url}}"}" + + # shellcheck disable=SC2016 + _UNEXPANDED_BIN_INSTALL_DIR='${HOME}/.local/bin' # Local directory to store executable (default: `$HOME/.local/bin`) + _EXPANDED_BIN_INSTALL_DIR="$(eval echo "${_UNEXPANDED_BIN_INSTALL_DIR}")" # Expand environment variables in path + _BIN_INSTALL_DIR="${_BIN_INSTALL_DIR:-${_EXPANDED_BIN_INSTALL_DIR}}" + + mkdir -p "${_BIN_INSTALL_DIR}" && + rm -rf "${_HYAKVNC_DIR}/hyakvnc-tmp" && + echo "Fetching hyakvnc from ${_HYAKVNC_REPO_URL}" 2>&1 && + git clone --depth 1 --single-branch --quiet "${_HYAKVNC_REPO_URL}" ~/.hyakvnc/hyakvnc-tmp && + rm -rf "${_HYAKVNC_REPO_DIR}" && + mv "${_HYAKVNC_DIR}/hyakvnc-tmp" "${_HYAKVNC_REPO_DIR}" && + ln -sf "${_HYAKVNC_REPO_DIR}/hyakvnc" "${_BIN_INSTALL_DIR}/hyakvnc" && + echo "Installed hyakvnc to ${_BIN_INSTALL_DIR}/hyakvnc linking to hyakvnc in ${_HYAKVNC_REPO_DIR}" 2>&1 || + return 1 +} + +if _install_hyakvnc; then + echo "Successfully installed hyakvnc." 2>&1 + if _add_hyakvnc_to_path; then + echo "Added hyakvnc to PATH." 2>&1 + else + echo "Could not add hyakvnc to PATH." 2>&1 + fi +else + echo "Failed to install hyakvnc." 2>&1 +fi + +# Unset all variables and functions defined in this script: +unset _HYAKVNC_DIR _HYAKVNC_REPO_DIR _HYAKVNC_REPO_URL _UNEXPANDED_BIN_INSTALL_DIR _EXPANDED_BIN_INSTALL_DIR _BIN_INSTALL_DIR +unset -f _install_hyakvnc _add_hyakvnc_to_path diff --git a/.github/workflows/build-documentation.yml b/.github/workflows/build-documentation.yml new file mode 100644 index 0000000..1a7f10c --- /dev/null +++ b/.github/workflows/build-documentation.yml @@ -0,0 +1,43 @@ +name: Build documentation and installer +"on": + push: + +jobs: + build-readme: + runs-on: ubuntu-latest + name: Build documentation and installer + permissions: write-all + steps: + - name: Check out code for the container build + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Build documentation and installer in one step + id: update-docs-and-installer + run: | + commit_msg="" + echo "Checking for changes in hyakvnc, .build/README.j2.md, and .github/workflows/build-documentation.yml" + if ! git --no-pager diff --name-only --quiet --diff-filter=AM ${{ github.event.before }} ${{ github.event.after }} -- hyakvnc .build/README.j2.md .build/install.j2.sh .github/workflows/build-documentation.yml; then + echo "Changes detected in hyakvnc, .build/README.j2.md, or .github/workflows/build-documentation.yml" + python3 -m pip install jinja-cli + pushd .build/ + sed -E '/^HYAKVNC_.*#\s*%%/!d; s/=.*(#\s*%%)/:/g; s/(^.)/- \1/g' ../hyakvnc > config.inc.md + for x in create status show stop config install; do ../hyakvnc help "$x" | sed -E '1 s/(.*)/\n### \1\n/; 2 s/^$/```text/' | pr -e4 -t && echo '```'; done > usage.inc.md + jinja -D github_repository "${{ github.repository }}" -D github_ref_name "${{ github.ref_name }}" README.j2.md | sed 's/^.*.*$//g' > ../README.md + jinja -D j2_hyakvnc_repo_url 'https://github.com/${{ github.repository }}' install.j2.sh -o ../install.sh + popd + + git config --local user.email "${{ github.event.sender.id }}+${{ github.event.sender.login }}@users.noreply.github.com" + git config --local user.name ${{ github.event.sender.login }} + + if ! git diff --quiet --stat README.md; then + git add README.md && commit_msg="Rebuilt README.md" + fi + + if ! git diff --quiet --stat install.sh; then + new_commit_msg="${commit_msg:-}" + [ -n "${new_commit_msg:-}" ] && new_commit_msg="${new_commit_msg} " + git add install.sh && new_commit_msg="Rebuilt install.sh" && commit_msg="${new_commit_msg:-}" + fi + git commit -am "${commit_msg}" && git push + fi diff --git a/.github/workflows/mkreadme.yml b/.github/workflows/mkreadme.yml deleted file mode 100644 index 7d98a26..0000000 --- a/.github/workflows/mkreadme.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: Build documentation -"on": - push: - -jobs: - build-readme: - runs-on: ubuntu-latest - name: Build README.md - permissions: write-all - steps: - - name: Install jinja-cli - run: | - python3 -m pip install jinja-cli - - name: Check out code for the container build - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Check if README.md has changed - id: readme-changed - run: | - if git --no-pager diff --name-only --quiet --diff-filter=AM ${{ github.event.before }} ${{ github.event.after }} -- hyakvnc .build/README.j2.md .github/workflows/mkreadme.yml; then - gh run cancel ${{ github.run_id }} - gh run watch ${{ github.run_id }} - fi - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Generate configuration descriptions - run: | - pushd .build/ - sed -E '/^HYAKVNC_.*#\s*%%/!d; s/=.*(#\s*%%)/:/g; s/(^.)/- \1/g' ../hyakvnc > config.inc.md - popd - - name: Generate usage descriptions - run: | - pushd .build/ - for x in create status show stop config install; do ../hyakvnc help "$x" | sed -E '1 s/(.*)/\n### \1\n/; 2 s/^$/```text/' | pr -e4 -t && echo '```'; done > usage.inc.md - popd - - name: Create and push README.md - run: | - pushd .build/ - jinja -D github_repository "${{ github.repository }}" -D github_ref_name "${{ github.ref_name }}" README.j2.md | sed 's/^.*.*$//g' > ../README.md - popd - git config --local user.email "${{ github.event.sender.id }}+${{ github.event.sender.login }}@users.noreply.github.com" - git config --local user.name ${{ github.event.sender.login }} - git add README.md - git commit -am "Update README.md" - git push diff --git a/README.md b/README.md index b3f2024..c3af2e1 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ hyakvnc -- A tool for launching VNC sessions on Hyak. `hyakvnc` is a command-line tool that makes it easy to start a graphical [VNC](https://en.wikipedia.org/wiki/Virtual_Network_Computing) session on the University of Washington [Hyak](https://hyak.uw.edu/) cluster, allowing you to interact with the system in a point-and-click environment, with support for graphical applications such as [Freesurfer](https://surfer.nmr.mgh.harvard.edu/). `hyakvnc` sessions run in [Apptainer](https://apptainer.org) containers, which provide reproducible environments that can run anywhere and be shared with other researchers. +*If you're already familiar with Hyak and VNC and you just want to install `hyakvnc` immediately, you can skip to the [quick install](#quick-install) section.* + ## Prerequisites Before running `hyakvnc`, you'll need the following: @@ -78,7 +80,7 @@ ssh your-uw-netid@klone.hyak.uw.edu After you've connected to the login node, you can download and install `hyakvnc` by running the following command. Copy and paste it into the terminal window where you are connected to the login node and press enter: ```bash -curl -o ~/.local/bin/hyakvnc --create-dirs -fsSL https://raw.githubusercontent.com/maouw/hyakvnc/main/hyakvnc && chmod +x ~/.local/bin/hyakvnc && [[ ":${PATH}:" != *":$HOME/.local/bin:"* ]] && export PATH="$HOME/.local/bin:$PATH" && [-n "${ZSH_VERSION:-}" ] && rehash +eval "$(curl -fsSL https://raw.githubusercontent.com//maouw/hyakvnc/install-sh/install.sh)" ``` This will download and install `hyakvnc` to your `~/.local/bin` directory and add it to your `$PATH` so you can run it by typing `hyakvnc` into the terminal window. @@ -88,7 +90,7 @@ This will download and install `hyakvnc` to your `~/.local/bin` directory and ad In a terminal window connected to a login node, enter this command to clone the repository and navigate into the repository directory: ```bash -git clone https://github.com/maouw/hyakvnc && cd hyakvnc +git clone --depth 1 --single-branch https://github.com/maouw/hyakvnc && cd hyakvnc ``` Then, run the following command to install `hyakvnc`: diff --git a/install.sh b/install.sh new file mode 100644 index 0000000..da58716 --- /dev/null +++ b/install.sh @@ -0,0 +1,70 @@ +#!/bin/sh + +# install.sh is generated from .build/install.j2.sh. Do not edit it directly. +# This script is intended to be sourced from the current shell. +# It will clone the hyakvnc repository from GitHub to ~/.hyakvnc/hyakvnc and create a symlink in it to ~/.local/bin/hyakvnc. +# These locations can be changed by setting the following environment variables: +# - HYAKVNC_DIR: Local directory to store application data (default: `$HOME/.hyakvnc`) +# - HYAKVNC_REPO_DIR: Local directory to store git repository (default: `$HYAKVNC_DIR/hyakvnc`) +# - HYAKVNC_REPO_URL: URL of the git repository to clone (default: https://github.com/maouw/hyakvnc) +# - BIN_INSTALL_DIR: Local directory to store executable (default: `$HOME/.local/bin`) + +_add_hyakvnc_to_path() { + [ -z "${_UNEXPANDED_BIN_INSTALL_DIR:-}" ] || [ -z "${_BIN_INSTALL_DIR:-}" ] && return 1 + case "${PATH:-}" in + *"${_BIN_INSTALL_DIR}"*) ;; + *) + if [ -n "${BASH_VERSION:-}" ]; then + echo "export PATH=\"${_UNEXPANDED_BIN_INSTALL_DIR}:\$PATH\"" >>"${HOME:-}/.bashrc" + echo "Added hyakvnc to PATH in ${HOME:-}/.bashrc" 2>&1 + export PATH="${_BIN_INSTALL_DIR}:${PATH:-}" + elif [ -n "${ZSH_VERSION:-}" ]; then + echo "export PATH=\"${_UNEXPANDED_BIN_INSTALL_DIR}:\$PATH\"" >>"${ZDOTDIR:-${HOME:-}}/.zshrc" && echo "Added hyakvnc to PATH in ${ZDOTDIR:-${HOME}}/.zshrc" 2>&1 + export PATH="${_BIN_INSTALL_DIR}:${PATH:-}" + rehash 2>/dev/null || true + elif [ "${0:-}" = "dash" ] || [ "${0:-}" = "sh" ]; then + echo "export PATH=\"${_UNEXPANDED_BIN_INSTALL_DIR}:\$PATH\"" >>"${HOME}/.profile" && echo "Added hyakvnc to PATH in ${HOME}/.profile" 2>&1 + export PATH="${_BIN_INSTALL_DIR}:${PATH:-}" + else + echo "Could not add hyakvnc to PATH." 2>&1 + return 1 + fi + ;; + esac +} + +_install_hyakvnc() { + _HYAKVNC_DIR="${_HYAKVNC_DIR:-${HOME}/.hyakvnc}" # %% Local directory to store application data (default: `$HOME/.hyakvnc`) + _HYAKVNC_REPO_DIR="${_HYAKVNC_REPO_DIR:-${_HYAKVNC_DIR}/hyakvnc}" # Local directory to store git repository (default: `$HYAKVNC_DIR/hyakvnc`) + _HYAKVNC_REPO_URL="${_HYAKVNC_REPO_URL:-"https://github.com/maouw/hyakvnc"}" + + # shellcheck disable=SC2016 + _UNEXPANDED_BIN_INSTALL_DIR='${HOME}/.local/bin' # Local directory to store executable (default: `$HOME/.local/bin`) + _EXPANDED_BIN_INSTALL_DIR="$(eval echo "${_UNEXPANDED_BIN_INSTALL_DIR}")" # Expand environment variables in path + _BIN_INSTALL_DIR="${_BIN_INSTALL_DIR:-${_EXPANDED_BIN_INSTALL_DIR}}" + + mkdir -p "${_BIN_INSTALL_DIR}" && + rm -rf "${_HYAKVNC_DIR}/hyakvnc-tmp" && + echo "Fetching hyakvnc from ${_HYAKVNC_REPO_URL}" 2>&1 && + git clone --depth 1 --single-branch --quiet "${_HYAKVNC_REPO_URL}" ~/.hyakvnc/hyakvnc-tmp && + rm -rf "${_HYAKVNC_REPO_DIR}" && + mv "${_HYAKVNC_DIR}/hyakvnc-tmp" "${_HYAKVNC_REPO_DIR}" && + ln -sf "${_HYAKVNC_REPO_DIR}/hyakvnc" "${_BIN_INSTALL_DIR}/hyakvnc" && + echo "Installed hyakvnc to ${_BIN_INSTALL_DIR}/hyakvnc linking to hyakvnc in ${_HYAKVNC_REPO_DIR}" 2>&1 || + return 1 +} + +if _install_hyakvnc; then + echo "Successfully installed hyakvnc." 2>&1 + if _add_hyakvnc_to_path; then + echo "Added hyakvnc to PATH." 2>&1 + else + echo "Could not add hyakvnc to PATH." 2>&1 + fi +else + echo "Failed to install hyakvnc." 2>&1 +fi + +# Unset all variables and functions defined in this script: +unset _HYAKVNC_DIR _HYAKVNC_REPO_DIR _HYAKVNC_REPO_URL _UNEXPANDED_BIN_INSTALL_DIR _EXPANDED_BIN_INSTALL_DIR _BIN_INSTALL_DIR +unset -f _install_hyakvnc _add_hyakvnc_to_path