[private] default: @just --list # ----------------Settings---------------- set fallback := true # ----------------Variables---------------- SQLITE_DB_FILE_PATH := 'state/keys-internal/keys.sqlite' # Regular expresion for sed cmd to match variants of Rust versions # Matched Rust versions: 1, 1.90, 1.90.0 SED_RUST_VERSION_REGEX := '[0-9](\.[0-9]+){1,2}' RUST_MANIFEST_STABLE_TOML_URL := 'https://static.rust-lang.org/dist/channel-rust-stable.toml' # Hierarchycal path in the file to current stable version RUST_MANIFEST_STABLE_VERSION_QUERY := 'pkg.rust.version' # Regex in sed(-r) format # Parsed string example: "1.90.0 (1159e78c4 2025-09-14)" RUST_MANIFEST_STABLE_VERSION_PARSE_REGEX := '^"([0-9]+).([0-9]+).([0-9]+) \(([0-9A-Fa-f]+) (([0-9]+)-([0-9]+)-([0-9]+))\)"$' # GOTCH: See documentation to `rust-stable-version` recipe for explanation on what \1, \2, etc. means. DEFAULT_RUST_STABLE_VERSION_FORMAT := '\1.\2' GITLAB_CI_FILE_NAME := '.gitlab-ci.yml' GITLAB_CI_FILE_PATH := absolute_path(GITLAB_CI_FILE_NAME) CARGO_FILE_NAME := 'Cargo.toml' CARGO_FILE_PATH := absolute_path(CARGO_FILE_NAME) CARGO_RUST_VERSION_QUERY := 'package.rust-version' CLIPPY_FILE_NAME := 'clippy.toml' CLIPPY_FILE_PATH := absolute_path(CLIPPY_FILE_NAME) CLIPPY_RUST_VERSION_QUERY := 'msrv' TOOLCHAIN_FILE_NAME := 'rust-toolchain.toml' TOOLCHAIN_FILE_PATH := absolute_path(TOOLCHAIN_FILE_NAME) TOOLCHAIN_RUST_VERSION_QUERY := 'toolchain.channel' GIT_BRANCH_NAME_PREFIX := 'upgrade_rust_to_' # ----------------Recipes---------------- # Perform initial setup of developer's system. [group('setup')] init: init-rocket-config # Copy Rocket's template configuration from Rocket.toml.dist to Rocket.toml. Rocket is Rust web framework. See https://rocket.rs/guide/v0.5/configuration/#configuration [group('setup')] init-rocket-config: #!/usr/bin/env -S bash -euo pipefail [ ! -f Rocket.toml ] \ && cp Rocket.toml.dist Rocket.toml \ && echo "Rocket.toml.dist copied to Rocket.toml" \ || echo "Rocket.toml exists already!" # Format justfile [group('fmt')] [group('format')] [group('just')] just-fmt: just --unstable --fmt # Format Rust code in all packages (aka path based dependencies) [group('fmt')] [group('format')] cargo-fmt: cargo fmt --all # Format all code [group('fmt')] [group('format')] fmt: just-fmt cargo-fmt alias f := fmt # Check justfile formatting [group('fmt')] [group('just')] [group('lint')] just-lint-fmt: just --unstable --fmt --check # Check Rust code formatting in all packages (aka path based dependencies) [group('fmt')] [group('lint')] cargo-lint-fmt: cargo fmt --all -- --check # Check formatting of all code [group('fmt')] [group('lint')] lint-fmt: just-lint-fmt cargo-lint-fmt alias lf := lint-fmt # Lint Rust code with Clippy [group('clippy')] [group('lint')] clippy-lint: cargo clippy --tests --no-deps --workspace alias cl := clippy-lint # Lint all code [group('lint')] lint: lint-fmt clippy-lint alias l := lint # Fix compilation warnings by applying compiler suggestions [group('fix')] cargo-fix *args: cargo fix --workspace {{ args }} # Apply Clippy's lint suggestions, i.e. fix Clippy linting warnings or errors [group('clippy')] [group('fix')] clippy-fix *args: cargo clippy --fix --tests --no-deps --workspace {{ args }} # Fix lint and compilation warnings and errors. Pass given arguments to all sub-recipes, i.e. `just fix --allow-dirty` calls `just cargo-fix --allow-dirty` and `just clippy-fix --allow-dirty`. [group('fix')] fix *args: (cargo-fix args) (clippy-fix args) # Check Rust code errors [group('compile')] check: cargo check alias c := check # Compile all Rust code [group('compile')] build *args='--workspace': cargo build {{ args }} alias b := build # Run all tests (i.e. --workspace), but when args given pass them to `cargo test`, e.g. `just test fs::tests::init` [group('test')] test args='--workspace': cargo test {{ args }} alias t := test # Run continuous check of Rust code errors. Detect file changes and repeat check automatically. Ctrl+c to exit. You can pass additional arguments, e.g. --notify (-N). [group('compile')] [group('watch')] watch-check *args: cargo watch --ignore *.pot {{ args }} alias wc := watch-check # Run web server and automatically restart on changes. Ctrl+c to exit. You can pass additional arguments, e.g. --notify (-N). [group('compile')] [group('run')] [group('watch')] watch-run *args: cargo watch --exec 'run --bin hagrid' --ignore *.pot {{ args }} alias wr := watch-run # Run tests every time files changed. Ctrl+c to exit. You can pass additional arguments, e.g. --notify (-N). [group('test')] [group('watch')] watch-test *args: cargo watch --exec 'test --workspace' --ignore *.pot {{ args }} alias wt := watch-test # Run web server [group('run')] run: cargo run alias r := run alias run-hagrid := run alias hagrid := run # Run "hagridctl" which automate some operations working with database externally, e.g. import keys [group('run')] run-hagridctl *args: cargo run --package hagridctl -- {{ args }} alias hagridctl := run-hagridctl # Run "tester" which allows to seed database with sample data, e.g. for testing [group('run')] run-tester *args: cargo run --package tester -- {{ args }} alias tester := run-tester # Clean compilation artifacts (i.e. "target" directory) [group('clean')] clean: cargo clean # Clean changes to translation files [group('clean')] [group('translation')] clean-translations: git restore po/ # Open database prompt [group('database')] @db: command -v sqlite3 \ && echo "See sqlite3 CLI Documentation: https://sqlite.org/cli.html\n" \ && sqlite3 {{ SQLITE_DB_FILE_PATH }} \ || echo "sqlite3 command has not been found. Please, install it using system's package manager or refer to documentation https://sqlite.org/cli.html for installation." >&2 # Upgrade Rust to a given version, by default current stable Rust version is used [group('housekeeping')] upgrade-rust version=`just _rust-stable-version`: _ensure-no-vcs-changes && _upgrade-rust-fixes-reminder #!/usr/bin/env -S bash -euo pipefail readonly OLD_VERSIONS=$( \ for recipe in _current-ci-rust-version _current-cargo-rust-version _current-clippy-rust-version _current-toolchain-rust-version; do \ just $recipe; \ done \ | sort -u \ ); \ just _upgrade-rust-git-create-branch "{{ replace(version, '.', '_') }}" "{{ GIT_BRANCH_NAME_PREFIX + replace(version, '.', '_') }}" for recipe in _upgrade-rust-ci _upgrade-rust-cargo _upgrade-rust-clippy _upgrade-rust-toolchain; do \ just $recipe '{{ version }}'; \ done \ just _upgrade-rust-git-commit \ "${OLD_VERSIONS//$'\n'/, }" \ "{{ version }}" \ "{{ GITLAB_CI_FILE_PATH }} {{ CARGO_FILE_PATH }} {{ CLIPPY_FILE_PATH }} {{ TOOLCHAIN_FILE_PATH }}" \ "{{ GITLAB_CI_FILE_NAME }} {{ CARGO_FILE_NAME }} {{ CLIPPY_FILE_NAME }} {{ TOOLCHAIN_FILE_NAME }}" _ensure-no-vcs-changes: #!/usr/bin/env -S bash -euo pipefail readonly CHANGED_FILES=$(git ls-files --deleted --modified --others --exclude-standard -- :/); \ git diff-index --quiet HEAD -- >&2 && true readonly HAS_STAGED_FILES=$? if [ -n "$CHANGED_FILES" ] || [ $HAS_STAGED_FILES != 0 ]; \ then \ echo -e "{{ RED }}You have working directory changes! \nTo avoid loosing or corrupting your changes commit or stash (git stash -u) them before running commands which change code automatically!{{ NORMAL }}"; \ exit 1; \ fi _upgrade-rust-git-create-branch branched_version branch_name: #!/usr/bin/env -S bash -euo pipefail readonly CURRENT_BRANCH=$(git branch --show-current) if [[ "$CURRENT_BRANCH" == *{{ branched_version }}* ]]; then echo "{{ GREEN }}It looks like you switched to new branch manually. Continue...{{ NORMAL }}" exit 0 fi while true; do read -p "Would you like to create new branch ({{ branch_name }})? [y/n]: " input case "$input" in y) break ;; n) exit 0 ;; *) echo "{{ RED }}Incorrect input. Please use only y or n.{{ NORMAL }}" ;; esac done git switch --create "{{ branch_name }}" _upgrade-rust-fixes-reminder: #!/usr/bin/env -S bash -euo pipefail echo -e "\n {{ YELLOW }}Don't forget to fix linting (just lint) and compilation (just check) warnings and errors!{{ NORMAL }}\n" [confirm('Would you like to commit changes? [y/n]')] _upgrade-rust-git-commit old_versions new_version file_paths file_names: #!/usr/bin/env -S bash -euo pipefail echo "Commiting changes ..."; \ git add {{ file_paths }}; \ sed -r 's/^ {4}//' <<'MSG' | git commit --file - Upgrade Rust toolchain: {{ old_versions }} -> {{ new_version }} If you don't have toolchain installed and you use rustup run: $ rustup toolchain install --profile default --component rustfmt,clippy {{ new_version }} NOTE: It might be that you have {{ new_version }}.0 installed as stable toolchain, in that case you still have to run the above command to install exactly {{ new_version }}. Command: `just upgrade-rust` Changes: - Upgrade version of used toolchain in the following places: {{ ' - ' + replace_regex(file_names, '\s+', "\n - ") }} MSG _upgrade-rust version file_path file_name current_version_recipe version_error_msg_part success_msg_part substitude_cmd: #!/usr/bin/env -S bash -euo pipefail readonly OLD=$(just {{ current_version_recipe }} {{ file_path }}); \ [ -z "$OLD" ] \ && ( \ echo "{{ RED }}{{ file_name }}{{ NORMAL }}: Can't determine {{ version_error_msg_part }} before upgrade" >&2; \ exit 1; \ ); \ sed -r -i "{{ substitude_cmd }}" {{ file_path }} \ && ( \ readonly NEW=$(just {{ current_version_recipe }} {{ file_path }}); \ [ -z "NEW" ] \ && ( \ echo "{{ RED }}{{ file_name }}{{ NORMAL }}: Can't determine {{ version_error_msg_part }} after upgrade" >&2; \ exit 1; \ ); \ echo "{{ GREEN }}{{ file_name }}{{ NORMAL }}: {{ success_msg_part }}: {{ BOLD }}$OLD{{ NORMAL }} -> {{ BOLD }}$NEW{{ NORMAL }}"; \ ) \ || echo "{{ RED }}{{ file_name }}{{ NORMAL }}: Upgrade failed" >&2 # Upgrade GitLab CI's Rust to a given version _upgrade-rust-ci version: (_upgrade-rust version GITLAB_CI_FILE_PATH GITLAB_CI_FILE_NAME '_current-ci-image' 'CI image version' 'image upgraded' 's|image:\s+\"rust:(' + SED_RUST_VERSION_REGEX + ')-([a-z]+)\"\s*$|image: \"rust:' + version + '-\3\"|') # Upgrade current Rust version in Cargo.toml _upgrade-rust-cargo version: (_upgrade-rust version CARGO_FILE_PATH CARGO_FILE_NAME '_current-cargo-rust-version' 'Rust version in ' + CARGO_FILE_NAME 'version upgraded' 's|rust-version\s*=\s*\"(' + SED_RUST_VERSION_REGEX + ')\"|rust-version = \"' + version + '\"|') # Upgrade current Rust version in clippy.toml _upgrade-rust-clippy version: (_upgrade-rust version CLIPPY_FILE_PATH CLIPPY_FILE_NAME '_current-clippy-rust-version' 'Rust version in ' + CLIPPY_FILE_NAME 'version upgraded' 's|msrv\s*=\s*\"(' + SED_RUST_VERSION_REGEX + ')\"|msrv = \"' + version + '\"|') # Upgrade current Rust version in rust-toolchain.toml _upgrade-rust-toolchain version: (_upgrade-rust version TOOLCHAIN_FILE_PATH TOOLCHAIN_FILE_NAME '_current-toolchain-rust-version' 'Rust version in ' + CLIPPY_FILE_NAME 'version upgraded' 's|channel\s*=\s*\"(' + SED_RUST_VERSION_REGEX + ')\"|channel = \"' + version + '\"|') # Get version of current stable Rust # # Parsed string example: "1.90.0 (1159e78c4 2025-09-14)" # Parsed components: # \1 - MAJOR # \2 - MINOR # \3 - PATCH # \4 - HASH # \5 - RELEASE DATE # \6 - RELEASE YEAR # \7 - RELEASE MONTH # \8 - RELEASE DAY # # Example of custom format: just rust-stable-version '\5 \4 \1.\2' # Ouputs: 2025-09-14 1159e78c4 1.90 _rust-stable-version format=DEFAULT_RUST_STABLE_VERSION_FORMAT: #!/usr/bin/env -S bash -euo pipefail curl -s {{ RUST_MANIFEST_STABLE_TOML_URL }} \ | tq {{ RUST_MANIFEST_STABLE_VERSION_QUERY }} \ | sed -rn 's|{{ RUST_MANIFEST_STABLE_VERSION_PARSE_REGEX }}|{{ format }}|p' # Extract current CI image in use _current-ci-image file_path=GITLAB_CI_FILE_PATH: #!/usr/bin/env -S bash -euo pipefail sed -rn "s|\s*image:\s+\"(rust:({{ SED_RUST_VERSION_REGEX }})-([a-z]+))\"\s*$|\1|p" "{{ file_path }}" _current-ci-rust-version file_path=GITLAB_CI_FILE_PATH: #!/usr/bin/env -S bash -euo pipefail sed -rn "s|\s*image:\s+\"rust:({{ SED_RUST_VERSION_REGEX }})-([a-z]+)\"\s*$|\1|p" "{{ file_path }}" # Extract current Rust version from Cargo.toml _current-cargo-rust-version file_path=CARGO_FILE_PATH: #!/usr/bin/env -S bash -euo pipefail tq --file "{{ file_path }}" --raw {{ CARGO_RUST_VERSION_QUERY }} # Extract current Rust version from clippy.toml _current-clippy-rust-version file_path=CLIPPY_FILE_PATH: #!/usr/bin/env -S bash -euo pipefail tq --file "{{ file_path }}" --raw {{ CLIPPY_RUST_VERSION_QUERY }} # Extract current Rust version from rust-toolchain.toml _current-toolchain-rust-version file_path=TOOLCHAIN_FILE_PATH: #!/usr/bin/env -S bash -euo pipefail tq --file "{{ file_path }}" --raw {{ TOOLCHAIN_RUST_VERSION_QUERY }}