use std::path::PathBuf;
use clap::{Args, Parser, Subcommand, ValueEnum};
use url::Url;
use vgi_forge::DEFAULT_REQUIRED_CHECK;
#[derive(Debug, Parser)]
#[command(name = "vgi", version, about, long_about = None)]
pub struct Cli {
#[command(subcommand)]
pub command: Command,
}
#[derive(Debug, Subcommand)]
pub enum Command {
#[command(subcommand)]
Repo(RepoCommand),
}
#[derive(Debug, Subcommand)]
pub enum RepoCommand {
Init(InitArgs),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
pub enum ForgeChoice {
Auto,
Github,
Forgejo,
}
const INIT_ABOUT: &str = "\
Turn VGI commit trust on for a repository in a manual or personal-account git \
namespace: the same bootstrap the community's bridge runs, done as you.
On GitHub it acts through your own `gh` login (`gh auth login`; you need admin \
on the repository). It commits `.github/workflows/verify-trust.yml` with the \
registry and VTC DIDs written in as literals, and the exempt web-flow keyring; \
removes stale TRUST_REGISTRY_DID / VTC_DID repository variables; and converges \
the \"VGI commit trust\" ruleset on the default branch: pull request required, \
\"Verify commit trust\" required and pinned to GitHub Actions, no force-push, no \
deletion, no bypass actors. The owners are the person running this (on a \
personal repository, the account holder) plus each --code-owner, counted once \
each. With two or more owners it also writes a managed `.github/CODEOWNERS` \
block and the ruleset requires a code owner's review, so no pull request can \
change the check it is judged by without another owner's approval. With one \
owner, only the check is required. On an organisation repository that is \
refused unless you pass --solo: anyone else in the organisation with write \
access could edit the workflow in the very pull request it judges.
These are per-repository guards. They are not the organisation's required \
workflow, which only the community's bridge sets.
On Forgejo it acts with FORGEJO_TOKEN (a token of yours with write:repository \
and read:user), sent only to the repository's own host and only after \
GET /api/v1/version, asked without it, answers as Forgejo or Gitea. It \
allows fast-forward-only merges, commits \
`.forgejo/workflows/verify-trust.yml` with the DIDs written in, and \
converges the default branch's protection: no pushes, the check's status \
context required, the workflow directories protected, applying to admins.
Every step is check-then-apply: a re-run changes nothing, and --dry-run \
prints each change (with the file or request body) without making it.
It does not tell the VTC the repository exists. That is `git-ns/repo/adopt`, \
a Trust Task signed with a VTA session, which this tool does not hold; it \
prints the `cnm git adopt` command to run instead.";
#[derive(Debug, Args)]
#[command(long_about = INIT_ABOUT)]
pub struct InitArgs {
#[arg(long, value_name = "DID")]
pub vtc: String,
#[arg(long, value_name = "HOST/OWNER/REPO")]
pub resource: Option<String>,
#[arg(long, value_name = "DID")]
pub registry: Option<String>,
#[arg(long = "owner", value_name = "DID")]
pub owners: Vec<String>,
#[arg(long, value_enum, default_value_t = ForgeChoice::Auto)]
pub forge: ForgeChoice,
#[arg(long = "code-owner", value_name = "LOGIN")]
pub code_owners: Vec<String>,
#[arg(long, conflicts_with = "code_owners")]
pub solo: bool,
#[arg(long, value_name = "FILE")]
pub platform_keyring: Option<PathBuf>,
#[arg(long, value_name = "REF")]
pub verify_trust_action: Option<String>,
#[arg(long, value_name = "TAG", default_value = concat!("v", env!("CARGO_PKG_VERSION")))]
pub verify_trust_version: String,
#[arg(long, value_name = "HEX")]
pub verify_trust_sha256: Option<String>,
#[arg(long, value_name = "NAME", default_value = DEFAULT_REQUIRED_CHECK)]
pub required_check: String,
#[arg(long, value_name = "URL")]
pub forgejo_url: Option<Url>,
#[arg(long, value_name = "LABEL", default_value = vgi_forge_forgejo::DEFAULT_RUNS_ON)]
pub runs_on: String,
#[arg(long)]
pub dry_run: bool,
}