{"record":{"id":"3e36633ba3bb83cb","repo":"dbt-labs/dbt-core","slug":"formula-filename-does-not-end-in-rb-filename","errorCode":null,"errorMessage":"formula filename does not end in .rb: {filename}","messagePattern":"formula filename does not end in \\.rb: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/dbt-ci/src/homebrew/publish.rs","lineNumber":52,"sourceCode":"            ExitCode::from(2)\n        }\n    }\n}\n\nfn run(args: HomebrewPublishArgs) -> Result<()> {\n    validate_release_version(&args.version)\n        .with_context(|| format!(\"invalid --version {:?}\", args.version))?;\n    if !args.formula.is_file() {\n        bail!(\"formula file not found: {}\", args.formula.display());\n    }\n    let filename = args\n        .formula\n        .file_name()\n        .and_then(|s| s.to_str())\n        .ok_or_else(|| anyhow!(\"formula path has no filename: {}\", args.formula.display()))?\n        .to_string();\n    if !filename.ends_with(\".rb\") {\n        bail!(\"formula filename does not end in .rb: {filename}\");\n    }\n\n    let token = read_token(&args.token_env, args.dry_run)?;\n    // For HTTPS tap URLs, build an `http.extraHeader` config knob carrying\n    // Basic auth credentials. Non-HTTPS URLs (file://, ssh) carry their\n    // own auth.\n    let auth_args = build_auth_args(&args.tap_repo, token.as_deref());\n\n    let work = TempDir::new(\"dbt-ci-brew-publish\")?;\n    eprintln!(\"→ git clone {} -> {}\", args.tap_repo, work.path().display());\n    let mut clone_argv: Vec<OsString> = auth_args.clone();\n    clone_argv.push(\"clone\".into());\n    if !is_local_path(&args.tap_repo) {\n        clone_argv.push(\"--depth\".into());\n        clone_argv.push(\"1\".into());\n    }\n    clone_argv.push(\"-b\".into());\n    clone_argv.push((&args.tap_branch).into());","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/dbt-ci/src/homebrew/publish.rs#L34-L70","documentation":"After extracting the formula's filename, `run` checks that it ends with the `.rb` extension required by Homebrew formulas. If the filename has any other extension (or none), the command aborts with `bail!`. Homebrew taps store formulas as Ruby files under `Formula/`, so a non-`.rb` file cannot be published.","triggerScenarios":"Running `dbt-ci homebrew publish` with a `--formula` path whose final filename component does not end in `.rb`, e.g. `--formula dist/dbt.txt`, `--formula ./formula`, or `--formula dbt`.","commonSituations":"Passing a release artifact (tarball, binary) instead of the formula file; a formula file that was renamed without the `.rb` extension; shell completion or scripting picking up the wrong file.","solutions":["Point `--formula` at the actual Ruby formula file ending in `.rb` (e.g., `Formula/dbt.rb`).","If the file is misnamed, rename it to include the `.rb` extension before publishing.","If you are publishing a release artifact, this is the wrong input; publish the formula file, not the artifact."],"exampleFix":"// before\ndbt-ci homebrew publish --formula ./dist/dbt-cli-linux.tar.gz\n// after\ndbt-ci homebrew publish --formula ./Formula/dbt.rb","handlingStrategy":"validation","validationCode":"use std::path::Path;\nfn validate_formula_extension(p: &Path) -> Result<(), String> {\n    let name = p.file_name().and_then(|s| s.to_str()).ok_or(\"path has no filename\")?;\n    if !name.ends_with(\".rb\") {\n        return Err(format!(\"formula filename does not end in .rb: {name}\"));\n    }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = publish(args) {\n    if e.to_string().contains(\"does not end in .rb\") {\n        eprintln!(\"--formula must point at a Homebrew .rb formula file, got: {}\", args.formula.display());\n        std::process::exit(2);\n    }\n    return Err(e);\n}","preventionTips":["Keep release artifacts and formula files in separate directories to avoid mixing them up in scripts.","Add shell completion or argument validation for --formula limited to *.rb.","In CI, derive the formula path from a glob like Formula/*.rb and assert exactly one match."],"tags":["cli","validation","homebrew","file-extension"],"backgroundTag":"invalid-argument-format","analyzedSha":"0267ce9170576975b76b64ce856b2e5848e96617","analyzedAt":"2026-09-07T21:53:39.732Z","contentChangedAt":"2026-09-07T21:53:39.732Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}