feat: use native repository credentials #66
@@ -1,58 +1,90 @@
|
||||
use syncode_runner_domain::{
|
||||
ControlVendor, IdentifierError, JobAssignment, SecretName, SecretValue,
|
||||
};
|
||||
use syncode_runner_source::{RepositoryCredential, RepositoryUrl};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
enum CredentialSecret {
|
||||
GiteaToken,
|
||||
GithubToken,
|
||||
}
|
||||
|
||||
pub fn repository_credential(
|
||||
assignment: &JobAssignment,
|
||||
vendor: ControlVendor,
|
||||
origin: RepositoryUrl,
|
||||
) -> Result<Option<RepositoryCredential>, IdentifierError> {
|
||||
for candidate in CredentialSecret::for_vendor(vendor) {
|
||||
if let Some(token) = secret(assignment, *candidate)? {
|
||||
return Ok(Some(RepositoryCredential::new(origin, token.clone())));
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
pub(crate) fn github_token(
|
||||
assignment: &JobAssignment,
|
||||
) -> Result<Option<&SecretValue>, IdentifierError> {
|
||||
secret(assignment, CredentialSecret::GithubToken)
|
||||
}
|
||||
|
||||
fn secret(
|
||||
assignment: &JobAssignment,
|
||||
candidate: CredentialSecret,
|
||||
) -> Result<Option<&SecretValue>, IdentifierError> {
|
||||
let name = candidate.as_ref().parse::<SecretName>()?;
|
||||
Ok(assignment.secrets.get(&name))
|
||||
}
|
||||
|
||||
impl CredentialSecret {
|
||||
const fn for_vendor(vendor: ControlVendor) -> &'static [Self] {
|
||||
match vendor {
|
||||
ControlVendor::SynCode | ControlVendor::Gitea | ControlVendor::Forgejo => {
|
||||
&[Self::GiteaToken, Self::GithubToken]
|
||||
}
|
||||
ControlVendor::GitHub => &[Self::GithubToken],
|
||||
ControlVendor::GitLab => &[],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for CredentialSecret {
|
||||
fn as_ref(&self) -> &str {
|
||||
match self {
|
||||
Self::GiteaToken => "GITEA_TOKEN",
|
||||
Self::GithubToken => "GITHUB_TOKEN",
|
||||
}
|
||||
}
|
||||
}
|
||||
use syncode_runner_domain::{
|
||||
ControlVendor, IdentifierError, JobAssignment, SecretName, SecretValue,
|
||||
};
|
||||
use syncode_runner_source::{RepositoryCredential, RepositoryUrl};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
enum CredentialSecret {
|
||||
SyncodeRepository,
|
||||
Gitea,
|
||||
Github,
|
||||
}
|
||||
|
||||
pub fn repository_credential(
|
||||
assignment: &JobAssignment,
|
||||
vendor: ControlVendor,
|
||||
origin: RepositoryUrl,
|
||||
) -> Result<Option<RepositoryCredential>, IdentifierError> {
|
||||
for candidate in CredentialSecret::for_vendor(vendor) {
|
||||
if let Some(token) = secret(assignment, *candidate)? {
|
||||
return Ok(Some(RepositoryCredential::new(origin, token.clone())));
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
pub(crate) fn github_token(
|
||||
assignment: &JobAssignment,
|
||||
) -> Result<Option<&SecretValue>, IdentifierError> {
|
||||
secret(assignment, CredentialSecret::Github)
|
||||
}
|
||||
|
||||
fn secret(
|
||||
assignment: &JobAssignment,
|
||||
candidate: CredentialSecret,
|
||||
) -> Result<Option<&SecretValue>, IdentifierError> {
|
||||
let name = candidate.as_ref().parse::<SecretName>()?;
|
||||
Ok(assignment.secrets.get(&name))
|
||||
}
|
||||
|
||||
impl CredentialSecret {
|
||||
const fn for_vendor(vendor: ControlVendor) -> &'static [Self] {
|
||||
match vendor {
|
||||
ControlVendor::SynCode => &[Self::SyncodeRepository, Self::Gitea, Self::Github],
|
||||
ControlVendor::Gitea | ControlVendor::Forgejo => &[Self::Gitea, Self::Github],
|
||||
ControlVendor::GitHub => &[Self::Github],
|
||||
ControlVendor::GitLab => &[],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for CredentialSecret {
|
||||
fn as_ref(&self) -> &str {
|
||||
match self {
|
||||
Self::SyncodeRepository => "SYNCODE_REPOSITORY_TOKEN",
|
||||
Self::Gitea => "GITEA_TOKEN",
|
||||
Self::Github => "GITHUB_TOKEN",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use syncode_runner_domain::ControlVendor;
|
||||
|
||||
use super::CredentialSecret;
|
||||
|
||||
#[test]
|
||||
fn syncode_prefers_the_native_repository_token() {
|
||||
let names = CredentialSecret::for_vendor(ControlVendor::SynCode)
|
||||
.iter()
|
||||
.map(AsRef::as_ref)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(
|
||||
names,
|
||||
vec!["SYNCODE_REPOSITORY_TOKEN", "GITEA_TOKEN", "GITHUB_TOKEN"]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn forge_controls_do_not_request_syncode_credentials() {
|
||||
for vendor in [ControlVendor::Gitea, ControlVendor::Forgejo] {
|
||||
assert!(
|
||||
CredentialSecret::for_vendor(vendor)
|
||||
.iter()
|
||||
.all(|candidate| candidate.as_ref() != "SYNCODE_REPOSITORY_TOKEN")
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user