mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-09-24 00:51:19 +00:00
GitHubAppCredentials now carries the configured app slug, so the "not installed" error from the installation lookup links to the specific app's install page (https://github.com/organizations/{owner}/settings/apps/{slug}/installations) when known, instead of the generic org installations page. Threaded through the server, workflow pipeline, and CLI runner. Also treat docker like daytona for GitHub credential gating: both are clone-based providers that need an installation token to fetch the repo, so a docker run now requires credentials when daytona would. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
46 lines
1.6 KiB
Rust
46 lines
1.6 KiB
Rust
use anyhow::anyhow;
|
|
use fabro_github::GitHubCredentials;
|
|
use fabro_static::EnvVars;
|
|
use fabro_types::settings::server::GithubIntegrationStrategy;
|
|
use fabro_vault::Vault;
|
|
|
|
pub(crate) fn build_github_credentials(
|
|
strategy: GithubIntegrationStrategy,
|
|
app_id: Option<&str>,
|
|
app_slug: Option<&str>,
|
|
vault: Option<&Vault>,
|
|
) -> anyhow::Result<Option<GitHubCredentials>> {
|
|
match strategy {
|
|
GithubIntegrationStrategy::App => {
|
|
GitHubCredentials::from_env_with_slug(app_id, app_slug).map_err(|err| anyhow!(err))
|
|
}
|
|
GithubIntegrationStrategy::Token => {
|
|
let token = lookup_github_token(vault);
|
|
match token {
|
|
Some(t) => Ok(Some(GitHubCredentials::Token(t))),
|
|
None => Err(anyhow!(
|
|
"GITHUB_TOKEN not configured — run fabro install or set GITHUB_TOKEN"
|
|
)),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Look up GitHub token: GITHUB_TOKEN env -> vault GITHUB_TOKEN -> GH_TOKEN env
|
|
/// -> vault GH_TOKEN
|
|
fn lookup_github_token(vault: Option<&Vault>) -> Option<String> {
|
|
lookup_env_or_vault(EnvVars::GITHUB_TOKEN, vault)
|
|
.or_else(|| lookup_env_or_vault(EnvVars::GH_TOKEN, vault))
|
|
}
|
|
|
|
#[expect(
|
|
clippy::disallowed_methods,
|
|
reason = "GitHub credential resolution intentionally falls back from vault to documented process-env names."
|
|
)]
|
|
fn lookup_env_or_vault(name: &str, vault: Option<&Vault>) -> Option<String> {
|
|
std::env::var(name)
|
|
.ok()
|
|
.or_else(|| vault.and_then(|v| v.get(name).map(str::to_string)))
|
|
.map(|t| t.trim().to_string())
|
|
.filter(|t| !t.is_empty())
|
|
}
|