chore: stop sharing a cache with the binary the audit job runs
This commit is contained in:
32
.gitignore
vendored
32
.gitignore
vendored
@@ -8,3 +8,35 @@ target/
|
||||
|
||||
# MSVC Windows builds of rustc generate these, which store debugging information
|
||||
*.pdb
|
||||
|
||||
# the cargo home CI keeps inside the project so it lands in the cache
|
||||
.cargo/
|
||||
|
||||
# where the completions build writes when it is not given a directory
|
||||
completions/
|
||||
|
||||
# os
|
||||
.DS_Store
|
||||
|
||||
# editors
|
||||
.vscode
|
||||
.idea
|
||||
.ignore
|
||||
|
||||
# ai
|
||||
CLAUDE.local.md
|
||||
.claude
|
||||
|
||||
# languages
|
||||
.python-version
|
||||
|
||||
# nix
|
||||
.nix-venv
|
||||
.envrc
|
||||
.direnv/
|
||||
|
||||
# project-local
|
||||
TODO.md
|
||||
# database dumps, which this tool exists to keep out of a repository
|
||||
dumps
|
||||
*.partial
|
||||
|
||||
@@ -5,30 +5,38 @@ default:
|
||||
files:
|
||||
- Cargo.lock
|
||||
paths:
|
||||
# no .cargo/bin here: the audit job runs what is in it, and this cache is
|
||||
# shared by every branch and merge request, so a pipeline could otherwise
|
||||
# leave behind the binary a later scheduled audit executes
|
||||
- .cargo/registry
|
||||
# so the audit job does not rebuild cargo-audit on every schedule
|
||||
- .cargo/bin
|
||||
- target
|
||||
|
||||
variables:
|
||||
# keep the registry inside the project so it lands in the cache
|
||||
CARGO_HOME: $CI_PROJECT_DIR/.cargo
|
||||
CARGO_TERM_COLOR: always
|
||||
# pinned, rather than whatever version exists on the night this runs
|
||||
CARGO_AUDIT_VERSION: "0.21.2"
|
||||
|
||||
# without this a push to a branch with an open merge request runs twice
|
||||
workflow:
|
||||
rules:
|
||||
# first, because a scheduled pipeline sets CI_COMMIT_BRANCH as well and so
|
||||
# would be matched by the branch rule below, or vetoed by the one above it
|
||||
- if: $CI_PIPELINE_SOURCE == "schedule"
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
|
||||
when: never
|
||||
- if: $CI_COMMIT_BRANCH
|
||||
- if: $CI_PIPELINE_SOURCE == "schedule"
|
||||
|
||||
check:
|
||||
script:
|
||||
- rustup component add rustfmt clippy
|
||||
- cargo fmt --check
|
||||
- cargo clippy --all-targets -- -D warnings
|
||||
# --locked on the first cargo invocation too: without it clippy resolves the
|
||||
# dependencies and rewrites a Cargo.lock that has drifted from Cargo.toml,
|
||||
# and the --locked commands after it then pass against what it just wrote
|
||||
- cargo clippy --locked --all-targets -- -D warnings
|
||||
- cargo test --locked
|
||||
- cargo build --release --locked
|
||||
rules:
|
||||
@@ -39,19 +47,33 @@ check:
|
||||
# runs only from a pipeline schedule, so set one up in the project settings
|
||||
audit:
|
||||
script:
|
||||
- cargo install cargo-audit --locked
|
||||
- cargo install cargo-audit --version $CARGO_AUDIT_VERSION --locked
|
||||
- cargo audit
|
||||
# reports dependencies that have drifted behind, without changing the lockfile
|
||||
- cargo update --dry-run
|
||||
# its own cache, so the audit tool is not rebuilt on every schedule while
|
||||
# still being written only by this schedule-only job. the pinned version is
|
||||
# part of the key, so a bump fetches rather than reusing the old binary
|
||||
cache:
|
||||
key: audit-tools-$CARGO_AUDIT_VERSION
|
||||
paths:
|
||||
- .cargo/bin
|
||||
- .cargo/registry
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "schedule"
|
||||
allow_failure: true
|
||||
|
||||
# the msrv declared in Cargo.toml, so it fails when something needs a newer rustc
|
||||
msrv:
|
||||
image: rust:1.85
|
||||
script:
|
||||
- cargo build --locked
|
||||
# its own key: artifacts built by another rustc are of no use to this job, and
|
||||
# sharing one only has the two toolchains taking turns overwriting it
|
||||
cache:
|
||||
key: msrv-$CI_COMMIT_REF_SLUG
|
||||
paths:
|
||||
- .cargo/registry
|
||||
- target
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "schedule"
|
||||
when: never
|
||||
|
||||
21
build.rs
21
build.rs
@@ -25,6 +25,14 @@ fn install_dir(shell: Shell) -> Option<(PathBuf, bool)> {
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Error> {
|
||||
// naming any rerun-if condition replaces cargo's default of re-running the
|
||||
// script whenever anything in the package changed, so everything that
|
||||
// shapes a completion script has to be named here. without them an
|
||||
// installed script goes stale against the binary it completes
|
||||
println!("cargo::rerun-if-changed=build.rs");
|
||||
println!("cargo::rerun-if-changed=src/cli");
|
||||
println!("cargo::rerun-if-changed=Cargo.toml");
|
||||
|
||||
println!("cargo::rerun-if-env-changed=SHELL_COMPLETIONS_DIR");
|
||||
for shell in Shell::value_variants() {
|
||||
println!(
|
||||
@@ -40,7 +48,18 @@ fn main() -> Result<(), Error> {
|
||||
continue;
|
||||
};
|
||||
|
||||
fs::create_dir_all(&dir)?;
|
||||
// a build script's working directory is the package root, so a relative
|
||||
// dir would quietly install into the source tree and one holding `..`
|
||||
// somewhere else again. only a path that says where it means is taken
|
||||
if requested && !dir.is_absolute() {
|
||||
return Err(Error::other(format!(
|
||||
"the completions directory must be an absolute path, not {}",
|
||||
dir.display()
|
||||
)));
|
||||
}
|
||||
|
||||
fs::create_dir_all(&dir)
|
||||
.map_err(|e| Error::other(format!("creating {}: {e}", dir.display())))?;
|
||||
let path = generate_to(*shell, &mut cmd, env!("CARGO_PKG_NAME"), &dir)?;
|
||||
|
||||
if requested {
|
||||
|
||||
@@ -9,7 +9,7 @@ pub enum Django {
|
||||
/// Start a bash session in a fresh django container
|
||||
Bash,
|
||||
|
||||
/// Prepare empty management command 'command' in app 'app'
|
||||
/// Prepare an empty management command NAME in the app at APP
|
||||
MakeCommand { app: PathBuf, name: String },
|
||||
|
||||
/// Run Django's manage.py makemigrations
|
||||
|
||||
@@ -27,15 +27,24 @@ fn script(shell: Shell) -> Vec<u8> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{Shell, script};
|
||||
use clap::ValueEnum;
|
||||
use super::{Ahab, Shell, script};
|
||||
use clap::{CommandFactory, ValueEnum};
|
||||
|
||||
#[test]
|
||||
fn every_shell_gets_a_script_covering_the_subcommands() {
|
||||
// asked of the parser rather than listed here, which is a list that
|
||||
// silently stops covering the newest command
|
||||
let subcommands: Vec<String> = Ahab::command()
|
||||
.get_subcommands()
|
||||
.map(|sub| sub.get_name().to_string())
|
||||
.collect();
|
||||
|
||||
assert!(subcommands.len() > 1, "{subcommands:?}");
|
||||
|
||||
for shell in Shell::value_variants() {
|
||||
let out = String::from_utf8(script(*shell)).expect("script is utf8");
|
||||
|
||||
for subcommand in ["django", "postgres", "link", "completions"] {
|
||||
for subcommand in &subcommands {
|
||||
assert!(
|
||||
out.contains(subcommand),
|
||||
"{shell:?} script never mentions {subcommand}"
|
||||
|
||||
Reference in New Issue
Block a user