set export := true
set shell := ['bash', '-euo', 'pipefail', '-c']

# Pre-installed on Sonoma:
#   * Skip upgrades: host, file, less, ps
#   * Upgrade: bash, curl, git (may come with xcode)

BRWS := 'asdf bash curl fping git gnu-sed tmux tree'
DEBS := 'bash bind9-host curl file fping git less procps tmux tree'
JUST := just_executable()
OPSY := `uname -s`

# List all recipes
default:
    {{ JUST }} --list

# print PATH and VERsion; optionally assert version file matches
pathver command version_file="":
    #!/usr/bin/env bash
    # TODO investigate require() instead
    source=$(type -p "{{ command }}")
    if [[ -z $source ]]; then
        source=$(type "{{ command }}")
    fi
    actual=$( "{{ command }}" --version 2>&1 | gsed -En 's/(.+ )?(v?[0-9]+\.[0-9]+\.[^ ]+).*/\2/p')
    echo "$source $actual"
    if [[ -f "{{ version_file }}" ]]; then
        expected=$(cat "{{ version_file }}")
        if [[ $actual != "$expected" && ${actual%.*} != "$expected" ]]; then
            echo "ERROR: $source version $actual does not match {{ version_file }} $expected"
            exit 1
        fi
    fi

# BUILD, check, and optionally upload python package with TWINE
build_twine upload='':
    bash .biobuddies/includes.bash build_twine {{ upload }}

# Docker Compose Build
dcb *args:
    docker compose --progress=plain build {{ args }}

# Docker Compose Django Manage
dcdm *args:
    docker compose exec `{{ JUST }} cona` python -m manage {{ args }}

# Docker Compose Push
dcp *args:
    docker compose push --quiet {{ args }}

# Docker Compose Run, respecting docker-compose.yaml port definitions
dcr *args:
    docker compose run --quiet-pull --service-ports {{ args }}

# Docker Compose Shell
dcs *args:
    docker compose run `{{ JUST }} cona` bash {{ args }}

# Docker Compose Up
dcu *args:
    docker compose up {{ args }}

# DEVelopment READYness check
devready:
    bash .biobuddies/includes.bash devready

# FORCE system to be READY for development, clobbering current settings
forceready:
    bash .biobuddies/includes.bash forceready

# print CodeNAme, a four letter acronym
cona:
    #!/usr/bin/env bash
    if [[ $GITHUB_REPOSITORY ]]; then
        echo "${GITHUB_REPOSITORY##*/}"
    elif [[ $VIRTUAL_ENV ]]; then
        basename "${VIRTUAL_ENV%/.venv}"
    else
        basename "$PWD"
    fi

# print ENVIronment, a four letter acronym
envi:
    #!/usr/bin/env bash
    if [[ $ENVI ]]; then
        echo "$ENVI"
    elif [[ $GITHUB_ACTIONS ]]; then
        echo github
    else
        echo local
    fi

# print GIt HAsh, a four letter acronym
giha:
    git describe --abbrev=40 --always --dirty --match=-

# Backwards compatibility alias for giha
gash: giha

# print ORGanizatioN, a four letter acronym
orgn:
    #!/usr/bin/env bash
    if [[ -n ${GITHUB_REPOSITORY_OWNER-} ]]; then
        echo "$GITHUB_REPOSITORY_OWNER";
    else
        # git will have colon :, https will have slash /
        git remote get-url origin | sed -E 's,.+github.com[:/]([^/]+).+,\1,';
    fi

# Pre-Commit Run (defaults to modified files)
pcr *args:
    {{ if `$JUST cona` == 'helicopyter' { '.venv/bin/python -m try_repo' } else { 'pre-commit run' } }} {{ args }}

# run Pre-Commit on All files
pca *args:
    @# Seemingly contradicting the help text, experimentation shows hook positional arguments must
    @# come before flags
    {{ JUST }} pcr {{ args }} --all-files

# run Pre-Commit on All files including Manual stage hooks
pcam *args:
    {{ JUST }} pca {{ args }} --hook-stage manual

# run Pre-Commit on modified files including Manual stage hooks
pcm *args:
    {{ JUST }} pcr {{ args }} --hook-stage manual

# git PUSH over https
push *args:
    git push https://${GITHUB_TOKEN}@github.com/{{ `$JUST orgn` }}/{{ `$JUST cona` }} {{ args }}

# Uv Pip Compile
upc *args:
    uv pip compile --all-extras --output-file requirements.txt --python-platform linux \
        pyproject.toml {{ if path_exists('requirements.in') == 'true' { 'requirements.in' } else { '' } }} {{ args }}

# Update asdf .tool-versions
update:
    echo "uv `asdf latest uv`" > .tool-versions

# Uv venv and Pip Sync
ups *args:
    uv venv --clear --no-progress && uv pip sync --no-progress {{ args }} requirements.txt

# Helicopyter Synth
hs cona='all':
    python -m helicopyter --format_with=${INSH_TF:-terraform} {{ cona }}

# Helicopyter synth and Terraform Apply
hta cona envi *args:
    #!/usr/bin/env bash
    if [[ "{{ envi }}" == "default" ]]; then
        echo 'The default workspace behaves inconsistently.'
        echo 'If you only have one environment, please name it `prod`.'
        exit 1
    fi
    {{ JUST }} hs {{ cona }} \
        && TF_VAR_giha=`{{ JUST }} giha` TF_VAR_tabr=`{{ JUST }} tabr` TF_WORKSPACE={{ envi }} \
            ${INSH_TF:-terraform} -chdir=deploys/{{ cona }}/terraform apply {{ args }}

# Helper for Terraform Init and synth
hti cona *args:
    ${INSH_TF:-terraform} -chdir=deploys/{{ cona }}/terraform init {{ args }}
    {{ JUST }} hs {{ cona }}

# Helicopyter synth and Terraform Plan
htp cona envi *args:
    #!/usr/bin/env bash
    if [[ "{{ envi }}" == "default" ]]; then
        echo 'The default workspace behaves inconsistently.'
        echo 'If you only have one environment, please name it `prod`.'
        exit 1
    fi
    {{ JUST }} hs {{ cona }} \
        && TF_WORKSPACE={{ envi }} ${INSH_TF:-terraform} -chdir=deploys/{{ cona }}/terraform plan \
        {{ args }}

# Universally Unique IDentifier
uuid:
    @echo {{ uuid() }}

# SUMMARIZE environment by displaying four letter acronyms
summarize:
    bash .biobuddies/includes.bash summarize

# Backwards compatibility alias for summarize
ghas: summarize

github_reference := env('GITHUB_HEAD_REF', env('GITHUB_REF_NAME', ''))

# print TAg or BRanch or empty string, a four letter acronym
tabr:
    @# remotes/origin/mybranch -> mybranch
    @# heads/mybranch -> mybranch
    @# tags/v2025.02.03 -> v2025.02.03
    @# heads/mybranch-dirty -> '' #empty string
    @echo {{ if github_reference == '' { `git describe --all --dirty --exact-match 2>/dev/null \
        | sed -En '/-dirty$/ q; s,(remotes/[^/]+|heads|tags)/,,p'` } else { github_reference } }}

# run TESTs and report uncovered lines
test *cover:
    .venv/bin/pytest --cov{{ if cover == '' { '' } else { '=' + cover } }} \
        --cov-report=term-missing:skip-covered --verbose
