# ~~~ Constants ~~~ LibName := "yary" LibMsrv := "1.53" # ~~~ Environment overrides ~~~ Color := env_var_or_default("YARY_COLOR", env_var_or_default("CARGO_TERM_COLOR", "1")) Dryrun := env_var_or_default("YARY_DRYRUN", None) Features := env_var_or_default("YARY_FEATURES", None) Profile := env_var_or_default("YARY_PROFILE", None) RustFlags := env_var_or_default("YARY_RUSTFLAGS", env_var_or_default("RUSTFLAGS", None)) DocFlags := env_var_or_default("YARY_RUSTDOCFLAGS", env_var_or_default("RUSTDOCFLAGS", None)) # Default to listing recipes _default: @just --list --list-prefix ' > ' # Display the recipe's steps show recipe: @just --show {{recipe}} # Open library documentation in your browser docs: (_build-docs "open") # Check the library for syntax errors check: @$Say "Checking library for syntax errors..." @$Cargo check # Print entire changelog changelog range=None: (_changelog range) # Print patch notes for unreleased changes patchnotes range=None: (_changelog if range != None { range } else { LibVersion + ".." } "all") # Build the library build: (_build Profile Features) # Build library documentation build-docs: _build-docs # Display dependency tree of the library deps edges="normal": _need_tree @$Cargo tree --edges {{edges}} # Display reverse dependency tree of the given crate rdeps crate=LibName edges="normal": _need_tree @$Cargo tree --invert --package {{crate}} --edges {{edges}} # Check for unused dependencies udeps: _need_udeps @$Say "Checking for unused dependencies..." @$Cargo +nightly udeps # Run unit tests test selector=None: (_test "lib" Profile Features selector) # Run documentation tests test-docs: (_test "doc" Profile Features) # Run example tests test-examples: (_test "examples" Profile Features) # Run entire test suite test-all: test test-docs test-examples lint-docs # Clean the local build artifacts clean: @$Say "Cleaning build artifacts..." @$Cargo clean # Clean the documentation artifacts clean-docs: @$Say "Cleaning documentation artifacts..." @$Cargo clean --doc # Clean the cargo binaries used by this repo (modifies ~/.cargo/bin) clean-bins: && _clean_deps @$Say "Cleaning Cargo binaries..." # Clean Cargo's cache (modifies ~/.cargo) clean-cache: _need_cache @$Say "Cleaning Cargo cache..." @$Cargo cache --auto-clean # Remove all local artifacts clean-all: clean clean-docs # Format library code fmt: (_format) # Initialize this library checkout, installing the required rustc version & components fresh-system: (_fresh-system LibMsrv) install-bins check # Install the cargo binaries used by this repo install-bins update=None: (_build_deps update) # Prune git local branches which previously had a tracking branch git-branch-prune: @$Say "Pruning [gone] branches..." @$Git fetch --prune --all --quiet && \ git for-each-ref --format '%(refname) %(upstream:track)' refs/heads \ | awk '$2 == "[gone]" {sub("refs/heads/", "", $1); print $1}' \ | xargs -n1 ${NODRYRUN:+$Git branch -D} # Run comprehensive check suite git-pre-push: lint build lint-docs udeps audit test-all alias pp := git-pre-push # Lint library code lint: (_format "check") _clippy # Lint library documentation lint-docs: (_build-docs "no-open" "check") # Audit dependencies, checking for any known vulnerabilities or CVEs audit: _need_audit @$Say "Auditing dependencies..." @$Say "[{{C_RED}}SKIP{{C_RESET}}] Tool is seg-faulting. See {{C_YELLOW}}https://github.com/rustsec/rustsec/issues/466{{C_RESET}}" @#$Cargo audit # Update the library's version to the specified bump-version to: (_bump-cargo-version "Cargo.toml" trim_start_match(to, "v")) check (_bump-git-version "v" + trim_start_match(to, "v")) @$Say "Run the following command when ready" @echo "{{C_RED}}==> {{C_GREEN}}git push --atomic origin master v{{trim_start_match(to, "v")}}{{C_RESET}}" # ~~~ Private recipes ~~~ # Run cargo test with the given suite, profile, features and selector (if any) _test $suite=None $profile=Profile $features=Features selector=None: @$Say "Running tests" \ "${suite:+{{C_GREEN}}suite:{{C_YELLOW}}$suite{{C_RESET}}}" \ "${features:+{{C_GREEN}}features:{{C_YELLOW}}$features{{C_RESET}}}" \ {{ if selector != None { C_GREEN + "selector:" + C_YELLOW + selector + C_RESET } else { None } }} \ | xargs @$Cargo test \ ${suite:+--$suite} \ ${features:+--features $features} \ {{ if profile =~ '(?i)^release$' { "--release" } else { None } }} \ {{selector}} # Run rustfmt with nightly so it understands our .rustfmt.toml rules _format $check=None: @$Say "Formating library..." @$Cargo +nightly fmt ${check:+--check} # Run clippy with the correct args _clippy: @$Say "Linting library..." @$Cargo clippy -- -D clippy::all -W clippy::style # Build the library _build $profile=Profile $features=Features: @$Say "Building library..." @$Cargo build \ {{ if profile =~ '(?i)^release$' { "--release" } else { None } }} \ ${features:+--features $features} # Build our documentation _build-docs open="no" check="no" features=Features: #!/bin/sh set -eu {{ if check =~ '(?i)^check|true|yes|1$' { 'export RUSTDOCFLAGS="$RUSTDOCFLAGS -Dwarnings"' } else { None } }} $Say "Building library docs..." $Cargo +nightly doc \ --document-private-items \ {{ if features != None { "--features " + features } else { "--all-features" } }} \ {{ if open =~ '(?i)^open|true|yes|1$' { "--open" } else { None } }} @_changelog range=None $strip=None $output=None +extra=None: _need_cliff $Cliff {{extra}} ${strip:+--strip $strip} ${output:+--output $output} {{range}} # Tiny perl script to bump the Cargo version field @_bump-cargo-version file $version temp=`mktemp`: $Say "Bumping {{file}} version to $version" $Perl -spe \ {{ if Dryrun != None { '"' } else { '' } }} \ 'if (/^version/) { s/("[\w.]+")/"$version"/ }' \ -- -version=$version < {{file}} > {{temp}} \ && mv -f {{temp}} {{file}} \ {{ if Dryrun != None { '"' } else { '' } }} # Add commit + tag to Git for the provided version @_bump-git-version version temp=`mktemp`: (_changelog LibVersion + ".." "all" temp "--tag" version "--body" '"$(cat .git-cliff/tag.tera)"') (_changelog None None "CHANGELOG.md" "--tag" version) $Say "Adding git tag {{version}} to HEAD" if ! git branch --show-current | grep -qF 'master'; then \ $Say 'Refusing to set git tag, branch is not master' && false; \ fi $Git add Cargo.toml Cargo.lock CHANGELOG.md $Git commit -m 'chore: release {{version}}' $Git tag -a {{version}} -F {{temp}} # Install rustc version that we use in this repo + all the components we're expecting @_fresh-system msrv=RustVersion: $Say "Installing Rust version {{msrv}}..." $Rustup install {{msrv}} $Rustup install nightly $Say "Setting override for {{justfile_directory()}}" $Rustup override set {{msrv}} $Say "Installing rustc components..." $Rustup component add rustfmt clippy rust-src $Rustup component add --toolchain nightly rustfmt clippy rust-docs # ~~~ Cargo binary management ~~~ _build_deps update=None: (_need_cache update) (_need_udeps update) (_need_audit update) (_need_tree update) (_need_cliff update) _clean_deps: _clean_cache _clean_udeps _clean_audit _clean_tree _clean_cliff # Cargo udeps _need_udeps update=None: (_need "udeps" update None "nightly") _clean_udeps: (_clean_need "udeps" "nightly") # Cargo cache _need_cache update=None: (_need "cache" update "no-default-features,ci-autoclean" "nightly") _clean_cache: (_clean_need "cache") # Cargo audit _need_audit update=None: (_need "audit" update None "nightly") _clean_audit: (_clean_need "audit") # Cargo tree _need_tree update=None: (_need "tree" update None "nightly") _clean_tree: (_clean_need "tree") # Git-cliff _need_cliff update=None: (_need "git-cliff" update None "nightly" None) _clean_cliff: (_clean_need "git-cliff") # Specify a dependency on a cargo binary @_need crate $update=None features=None $nightly=None prefix="cargo-": needed={{ if prefix != None { prefix + crate } else { crate } }}; \ {{ if update == None { "command -v $needed 2>/dev/null 1>/dev/null" } else { "false" } }} \ || $Cargo ${nightly:++nightly} install \ ${update:+--force} \ {{ if features =~ "no-default-features" { "--no-default-features" } else { None } }} \ {{ if features != None { "--features " + replace(features, "no-default-features,", None)} else { None } }} \ $needed # Clean a cargo binary @_clean_need crate $nightly=None: needed=cargo-{{crate}}; \ command -v $needed 2>/dev/null 1>/dev/null \ && $Cargo ${nightly:++nightly} uninstall $needed \ || true # ~~~ Global shell variables ~~~ export Say := "echo " + C_RED + "==> " + C_RESET + BuildId export Cargo := if Dryrun == None { "cargo" } else { DryrunPrefix + "cargo" } export Rustup := if Dryrun == None { "rustup" } else { DryrunPrefix + "cargo" } export Git := if Dryrun == None { "git" } else { DryrunPrefix + "git" } export Sed := if Dryrun == None { "sed" } else { DryrunPrefix + "sed" } export Perl := if Dryrun == None { "perl" } else { DryrunPrefix + "perl" } export Cliff := if Dryrun == None { "git-cliff" } else { DryrunPrefix + "git-cliff" } export DRYRUN := if Dryrun == None { None } else { "1" } export NODRYRUN := if Dryrun == None { "1" } else { None } export RUSTFLAGS := RustFlags export RUSTDOCFLAGS := DocFlags # Nicer name for empty strings None := "" # ~~~ Contextual information ~~~ GitCommitish := if `git tag --points-at HEAD` != None { `git tag --points-at HEAD` } else if `git branch --show-current` != None { `git branch --show-current` } else { `git rev-parse --short HEAD` } RustVersion := `rustc --version | cut -d' ' -f2` LibVersion := `git describe --abbrev=0 2>/dev/null || echo -n "0.0.0"` DryrunPrefix := "echo " + "[" + C_GREEN + "DRYRUN" + C_RESET + "] " BuildId := "[" + C_YELLOW + RustVersion + C_RESET + "/" + C_GREEN + LibName + C_RESET + "@" + C_CYAN + GitCommitish + C_RESET + "]" # ~~~ Color Codes ~~~ C_ENABLED := if Color =~ '(?i)^auto|always|yes|1$' { "1" } else { None } C_RESET := if C_ENABLED == "1" { `echo -e "\033[0m"` } else { None } C_BLACK := if C_ENABLED == "1" { `echo -e "\033[0;30m"` } else { None } C_RED := if C_ENABLED == "1" { `echo -e "\033[0;31m"` } else { None } C_GREEN := if C_ENABLED == "1" { `echo -e "\033[0;32m"` } else { None } C_YELLOW := if C_ENABLED == "1" { `echo -e "\033[0;33m"` } else { None } C_BLUE := if C_ENABLED == "1" { `echo -e "\033[0;34m"` } else { None } C_MAGENTA := if C_ENABLED == "1" { `echo -e "\033[0;35m"` } else { None } C_CYAN := if C_ENABLED == "1" { `echo -e "\033[0;36m"` } else { None } C_WHITE := if C_ENABLED == "1" { `echo -e "\033[0;37m"` } else { None }