fix: Remove hard requirement for login creds to be able to push (#187)

Related to https://github.com/blue-build/github-action/issues/48
This commit is contained in:
Gerald Pinder 2024-05-28 22:56:06 -04:00 committed by GitHub
parent 02b2fe5434
commit 9dd1ec90f4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 104 additions and 95 deletions

View file

@ -12,7 +12,7 @@ version = "0.8.9"
[workspace.dependencies] [workspace.dependencies]
anyhow = "1" anyhow = "1"
chrono = "0.4" chrono = "0.4"
clap = { version = "4", features = ["derive", "cargo", "unicode"] } clap = "4"
colored = "2" colored = "2"
env_logger = "0.11" env_logger = "0.11"
format_serde_error = "0.3" format_serde_error = "0.3"
@ -74,7 +74,7 @@ users = "0.11"
# Workspace dependencies # Workspace dependencies
anyhow.workspace = true anyhow.workspace = true
chrono.workspace = true chrono.workspace = true
clap.workspace = true clap = { workspace = true, features = ["derive", "cargo", "unicode", "env"] }
colored.workspace = true colored.workspace = true
env_logger.workspace = true env_logger.workspace = true
indexmap.workspace = true indexmap.workspace = true

View file

@ -7,11 +7,12 @@ use std::{
use anyhow::{bail, Context, Result}; use anyhow::{bail, Context, Result};
use blue_build_recipe::Recipe; use blue_build_recipe::Recipe;
use blue_build_utils::constants::{ use blue_build_utils::constants::{
ARCHIVE_SUFFIX, BUILD_ID_LABEL, CI_DEFAULT_BRANCH, CI_PROJECT_NAME, CI_PROJECT_NAMESPACE, ARCHIVE_SUFFIX, BB_PASSWORD, BB_REGISTRY, BB_REGISTRY_NAMESPACE, BB_USERNAME, BUILD_ID_LABEL,
CI_PROJECT_URL, CI_REGISTRY, CI_SERVER_HOST, CI_SERVER_PROTOCOL, CONFIG_PATH, CONTAINER_FILE, CI_DEFAULT_BRANCH, CI_PROJECT_NAME, CI_PROJECT_NAMESPACE, CI_PROJECT_URL, CI_REGISTRY,
COSIGN_PATH, COSIGN_PRIVATE_KEY, GITHUB_REPOSITORY_OWNER, GITHUB_TOKEN, CI_SERVER_HOST, CI_SERVER_PROTOCOL, CONFIG_PATH, CONTAINER_FILE, COSIGN_PATH,
GITHUB_TOKEN_ISSUER_URL, GITHUB_WORKFLOW_REF, GITIGNORE_PATH, LABELED_ERROR_MESSAGE, COSIGN_PRIVATE_KEY, GITHUB_REPOSITORY_OWNER, GITHUB_TOKEN, GITHUB_TOKEN_ISSUER_URL,
NO_LABEL_ERROR_MESSAGE, RECIPE_FILE, RECIPE_PATH, SIGSTORE_ID_TOKEN, GITHUB_WORKFLOW_REF, GITIGNORE_PATH, LABELED_ERROR_MESSAGE, NO_LABEL_ERROR_MESSAGE,
RECIPE_FILE, RECIPE_PATH, SIGSTORE_ID_TOKEN,
}; };
use clap::Args; use clap::Args;
use colored::Colorize; use colored::Colorize;
@ -20,7 +21,7 @@ use typed_builder::TypedBuilder;
use crate::{ use crate::{
commands::generate::GenerateCommand, commands::generate::GenerateCommand,
credentials, credentials::{self, Credentials},
drivers::{ drivers::{
opts::{BuildTagPushOpts, CompressionType, GetMetadataOpts}, opts::{BuildTagPushOpts, CompressionType, GetMetadataOpts},
Driver, Driver,
@ -78,26 +79,26 @@ pub struct BuildCommand {
archive: Option<PathBuf>, archive: Option<PathBuf>,
/// The registry's domain name. /// The registry's domain name.
#[arg(long)] #[arg(long, env = BB_REGISTRY)]
#[builder(default, setter(into, strip_option))] #[builder(default, setter(into, strip_option))]
registry: Option<String>, registry: Option<String>,
/// The url path to your base /// The url path to your base
/// project images. /// project images.
#[arg(long)] #[arg(long, env = BB_REGISTRY_NAMESPACE)]
#[builder(default, setter(into, strip_option))] #[builder(default, setter(into, strip_option))]
#[arg(visible_alias("registry-path"))] #[arg(visible_alias("registry-path"))]
registry_namespace: Option<String>, registry_namespace: Option<String>,
/// The username to login to the /// The username to login to the
/// container registry. /// container registry.
#[arg(short = 'U', long)] #[arg(short = 'U', long, env = BB_USERNAME, hide_env_values = true)]
#[builder(default, setter(into, strip_option))] #[builder(default, setter(into, strip_option))]
username: Option<String>, username: Option<String>,
/// The password to login to the /// The password to login to the
/// container registry. /// container registry.
#[arg(short = 'P', long)] #[arg(short = 'P', long, env = BB_PASSWORD, hide_env_values = true)]
#[builder(default, setter(into, strip_option))] #[builder(default, setter(into, strip_option))]
password: Option<String>, password: Option<String>,
@ -129,6 +130,8 @@ impl BlueBuildCommand for BuildCommand {
check_cosign_files()?; check_cosign_files()?;
} }
Self::login()?;
// Check if the Containerfile exists // Check if the Containerfile exists
// - If doesn't => *Build* // - If doesn't => *Build*
// - If it does: // - If it does:
@ -213,10 +216,6 @@ impl BuildCommand {
let tags = recipe.generate_tags(os_version); let tags = recipe.generate_tags(os_version);
let image_name = self.generate_full_image_name(&recipe)?; let image_name = self.generate_full_image_name(&recipe)?;
if self.push {
Self::login()?;
}
let opts = if let Some(archive_dir) = self.archive.as_ref() { let opts = if let Some(archive_dir) = self.archive.as_ref() {
BuildTagPushOpts::builder() BuildTagPushOpts::builder()
.archive_path(format!( .archive_path(format!(
@ -253,32 +252,31 @@ impl BuildCommand {
trace!("BuildCommand::login()"); trace!("BuildCommand::login()");
info!("Attempting to login to the registry"); info!("Attempting to login to the registry");
let credentials = credentials::get()?; if let Some(Credentials {
registry,
username,
password,
}) = credentials::get()
{
info!("Logging into the registry, {registry}");
Driver::get_build_driver().login()?;
let (registry, username, password) = ( trace!("cosign login -u {username} -p [MASKED] {registry}");
&credentials.registry, let login_output = Command::new("cosign")
&credentials.username, .arg("login")
&credentials.password, .arg("-u")
); .arg(username)
.arg("-p")
.arg(password)
.arg(registry)
.output()?;
info!("Logging into the registry, {registry}"); if !login_output.status.success() {
Driver::get_build_driver().login()?; let err_output = String::from_utf8_lossy(&login_output.stderr);
bail!("Failed to login for cosign: {err_output}");
trace!("cosign login -u {username} -p [MASKED] {registry}"); }
let login_output = Command::new("cosign") info!("Login success at {registry}");
.arg("login")
.arg("-u")
.arg(username)
.arg("-p")
.arg(password)
.arg(registry)
.output()?;
if !login_output.status.success() {
let err_output = String::from_utf8_lossy(&login_output.stderr);
bail!("Failed to login for cosign: {err_output}");
} }
info!("Login success at {registry}");
Ok(()) Ok(())
} }

View file

@ -128,9 +128,7 @@ pub fn set_user_creds(
/// ///
/// # Errors /// # Errors
/// Will error if there aren't any credentials available. /// Will error if there aren't any credentials available.
pub fn get() -> Result<&'static Credentials> { pub fn get() -> Option<&'static Credentials> {
trace!("credentials::get()"); trace!("credentials::get()");
ENV_CREDENTIALS ENV_CREDENTIALS.as_ref()
.as_ref()
.ok_or_else(|| anyhow!("No credentials available"))
} }

View file

@ -5,7 +5,7 @@ use log::{error, info, trace};
use semver::Version; use semver::Version;
use serde::Deserialize; use serde::Deserialize;
use crate::credentials; use crate::credentials::{self, Credentials};
use super::{ use super::{
opts::{BuildOpts, PushOpts, TagOpts}, opts::{BuildOpts, PushOpts, TagOpts},
@ -109,22 +109,26 @@ impl BuildDriver for BuildahDriver {
fn login(&self) -> Result<()> { fn login(&self) -> Result<()> {
trace!("BuildahDriver::login()"); trace!("BuildahDriver::login()");
let (registry, username, password) = if let Some(Credentials {
credentials::get().map(|c| (&c.registry, &c.username, &c.password))?; registry,
username,
password,
}) = credentials::get()
{
trace!("buildah login -u {username} -p [MASKED] {registry}");
let output = Command::new("buildah")
.arg("login")
.arg("-u")
.arg(username)
.arg("-p")
.arg(password)
.arg(registry)
.output()?;
trace!("buildah login -u {username} -p [MASKED] {registry}"); if !output.status.success() {
let output = Command::new("buildah") let err_out = String::from_utf8_lossy(&output.stderr);
.arg("login") bail!("Failed to login for buildah: {err_out}");
.arg("-u") }
.arg(username)
.arg("-p")
.arg(password)
.arg(registry)
.output()?;
if !output.status.success() {
let err_out = String::from_utf8_lossy(&output.stderr);
bail!("Failed to login for buildah: {err_out}");
} }
Ok(()) Ok(())
} }

View file

@ -13,7 +13,7 @@ use once_cell::sync::Lazy;
use semver::Version; use semver::Version;
use serde::Deserialize; use serde::Deserialize;
use crate::image_metadata::ImageMetadata; use crate::{credentials::Credentials, image_metadata::ImageMetadata};
use super::{ use super::{
credentials, credentials,
@ -169,22 +169,26 @@ impl BuildDriver for DockerDriver {
fn login(&self) -> Result<()> { fn login(&self) -> Result<()> {
trace!("DockerDriver::login()"); trace!("DockerDriver::login()");
let (registry, username, password) = if let Some(Credentials {
credentials::get().map(|c| (&c.registry, &c.username, &c.password))?; registry,
username,
password,
}) = credentials::get()
{
trace!("docker login -u {username} -p [MASKED] {registry}");
let output = Command::new("docker")
.arg("login")
.arg("-u")
.arg(username)
.arg("-p")
.arg(password)
.arg(registry)
.output()?;
trace!("docker login -u {username} -p [MASKED] {registry}"); if !output.status.success() {
let output = Command::new("docker") let err_out = String::from_utf8_lossy(&output.stderr);
.arg("login") bail!("Failed to login for docker: {err_out}");
.arg("-u") }
.arg(username)
.arg("-p")
.arg(password)
.arg(registry)
.output()?;
if !output.status.success() {
let err_out = String::from_utf8_lossy(&output.stderr);
bail!("Failed to login for docker: {err_out}");
} }
Ok(()) Ok(())
} }

View file

@ -6,7 +6,7 @@ use log::{debug, error, info, trace};
use semver::Version; use semver::Version;
use serde::Deserialize; use serde::Deserialize;
use crate::image_metadata::ImageMetadata; use crate::{credentials::Credentials, image_metadata::ImageMetadata};
use super::{ use super::{
credentials, credentials,
@ -120,22 +120,26 @@ impl BuildDriver for PodmanDriver {
fn login(&self) -> Result<()> { fn login(&self) -> Result<()> {
trace!("PodmanDriver::login()"); trace!("PodmanDriver::login()");
let (registry, username, password) = if let Some(Credentials {
credentials::get().map(|c| (&c.registry, &c.username, &c.password))?; registry,
username,
password,
}) = credentials::get()
{
trace!("podman login -u {username} -p [MASKED] {registry}");
let output = Command::new("podman")
.arg("login")
.arg("-u")
.arg(username)
.arg("-p")
.arg(password)
.arg(registry)
.output()?;
trace!("podman login -u {username} -p [MASKED] {registry}"); if !output.status.success() {
let output = Command::new("podman") let err_out = String::from_utf8_lossy(&output.stderr);
.arg("login") bail!("Failed to login for podman: {err_out}");
.arg("-u") }
.arg(username)
.arg("-p")
.arg(password)
.arg(registry)
.output()?;
if !output.status.success() {
let err_out = String::from_utf8_lossy(&output.stderr);
bail!("Failed to login for podman: {err_out}");
} }
Ok(()) Ok(())
} }

View file

@ -17,6 +17,7 @@ which = "6"
anyhow.workspace = true anyhow.workspace = true
chrono.workspace = true chrono.workspace = true
clap = { workspace = true, features = ["derive"] }
colored.workspace = true colored.workspace = true
env_logger.workspace = true env_logger.workspace = true
format_serde_error.workspace = true format_serde_error.workspace = true
@ -25,10 +26,6 @@ serde.workspace = true
serde_yaml.workspace = true serde_yaml.workspace = true
serde_json.workspace = true serde_json.workspace = true
[dependencies.clap]
workspace = true
features = ["derive"]
[build-dependencies] [build-dependencies]
syntect = "5.2.0" syntect = "5.2.0"

View file

@ -17,6 +17,10 @@ pub const IMAGE_VERSION_LABEL: &str = "org.opencontainers.image.version";
// BlueBuild vars // BlueBuild vars
pub const BB_BUILDKIT_CACHE_GHA: &str = "BB_BUILDKIT_CACHE_GHA"; pub const BB_BUILDKIT_CACHE_GHA: &str = "BB_BUILDKIT_CACHE_GHA";
pub const BB_PASSWORD: &str = "BB_PASSWORD";
pub const BB_REGISTRY: &str = "BB_REGISTRY";
pub const BB_REGISTRY_NAMESPACE: &str = "BB_REGISTRY_NAMESPACE";
pub const BB_USERNAME: &str = "BB_USERNAME";
// Docker vars // Docker vars
pub const DOCKER_HOST: &str = "DOCKER_HOST"; pub const DOCKER_HOST: &str = "DOCKER_HOST";