Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make it easier to test without GitHub or a local FlakeHub #164

Merged
merged 3 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,17 @@ cargo run -- \
--jwt-issuer-uri http://localhost:8081/jwt/token \
--host http://localhost:8080
```

To test evaluation of a local flake without fetching anything from
GitHub, and writing the tarball and metadata to a local directory
instead of FlakeHub, do:

```bash
cargo run -- \
--visibility public \
--repository foo/bar \
--tag v0.0.1 \
--git-root /path/to/repo \
--directory /path/to/repo/flake \
--dest-dir /tmp/out
```
105 changes: 104 additions & 1 deletion src/cli/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
mod instrumentation;

use std::path::PathBuf;
use std::path::{Path, PathBuf};
use std::str::FromStr as _;

use color_eyre::eyre::{eyre, Context as _, Result};

use crate::git_context::GitContext;
use crate::push_context::ExecutionEnvironment;
use crate::{Visibility, DEFAULT_ROLLING_PREFIX};

#[derive(Debug, clap::Parser)]
#[clap(version)]
Expand Down Expand Up @@ -118,6 +125,10 @@ pub(crate) struct FlakeHubPushCli {
default_value_t = false
)]
pub(crate) disable_rename_subgroups: bool,

/// Write the tarball to a directory instead of pushing it to FlakeHub.
#[clap(long, env = "FLAKEHUB_DEST_DIR", value_parser = PathBufToNoneParser, default_value = "")]
pub(crate) dest_dir: OptionPathBuf,
}

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -320,4 +331,96 @@ impl FlakeHubPushCli {
}
}
}

pub(crate) fn execution_environment(&self) -> ExecutionEnvironment {
if std::env::var("GITHUB_ACTION").ok().is_some() {
ExecutionEnvironment::GitHub
} else if std::env::var("GITLAB_CI").ok().is_some() {
ExecutionEnvironment::GitLab
} else {
ExecutionEnvironment::LocalGitHub
}
}

pub(crate) fn visibility(&self) -> Result<Visibility> {
match (self.visibility_alt, self.visibility) {
(Some(v), _) => Ok(v),
(None, Some(v)) => Ok(v),
(None, None) => Err(color_eyre::eyre::eyre!(
"Could not determine the flake's desired visibility. Use `--visibility` to set this to one of the following: public, unlisted, private.",
)),
}
}

pub(crate) fn resolve_local_git_root(&self) -> Result<PathBuf> {
let maybe_git_root = match &self.git_root.0 {
Some(gr) => Ok(gr.to_owned()),
None => std::env::current_dir().map(PathBuf::from),
};

let local_git_root = maybe_git_root.wrap_err("Could not determine current `git_root`. Pass `--git-root` or set `FLAKEHUB_PUSH_GIT_ROOT`, or run `flakehub-push` with the git root as the current working directory")?;
let local_git_root = local_git_root
.canonicalize()
.wrap_err("Failed to canonicalize `--git-root` argument")?;

Ok(local_git_root)
}

pub(crate) fn subdir_from_git_root(&self, local_git_root: &Path) -> Result<PathBuf> {
let subdir =
if let Some(directory) = &self.directory.0 {
let absolute_directory = if directory.is_absolute() {
directory.clone()
} else {
local_git_root.join(directory)
};
let canonical_directory = absolute_directory
.canonicalize()
.wrap_err("Failed to canonicalize `--directory` argument")?;

PathBuf::from(canonical_directory.strip_prefix(local_git_root).wrap_err(
"Specified `--directory` was not a directory inside the `--git-root`",
)?)
} else {
PathBuf::new()
};

Ok(subdir)
}

pub(crate) fn release_version(&self, git_ctx: &GitContext) -> Result<String> {
let rolling_prefix_or_tag = match (self.rolling_minor.0.as_ref(), &self.tag.0) {
(Some(_), _) if !self.rolling => {
return Err(eyre!(
"You must enable `rolling` to upload a release with a specific `rolling-minor`."
));
}
(Some(minor), _) => format!("0.{minor}"),
(None, _) if self.rolling => DEFAULT_ROLLING_PREFIX.to_string(),
(None, Some(tag)) => {
let version_only = tag.strip_prefix('v').unwrap_or(tag);
// Ensure the version respects semver
semver::Version::from_str(version_only).wrap_err_with(|| eyre!("Failed to parse version `{tag}` as semver, see https://semver.org/ for specifications"))?;
tag.to_string()
}
(None, None) => {
return Err(eyre!("Could not determine tag or rolling minor version, `--tag`, `GITHUB_REF_NAME`, or `--rolling-minor` must be set"));
}
};

let Some(commit_count) = git_ctx.revision_info.commit_count else {
return Err(eyre!("Could not determine commit count, this is normally determined via the `--git-root` argument or via the GitHub API"));
};

let rolling_minor_with_postfix_or_tag = if self.rolling_minor.0.is_some() || self.rolling {
format!(
"{rolling_prefix_or_tag}.{}+rev-{}",
commit_count, git_ctx.revision_info.revision
)
} else {
rolling_prefix_or_tag.to_string() // This will always be the tag since `self.rolling_prefix` was empty.
};

Ok(rolling_minor_with_postfix_or_tag)
}
}
44 changes: 39 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,45 @@ async fn main() -> Result<std::process::ExitCode> {
}

async fn execute() -> Result<std::process::ExitCode> {
let ctx = {
let mut cli = cli::FlakeHubPushCli::parse();
cli.instrumentation.setup()?;
PushContext::from_cli_and_env(&mut cli).await?
};
let mut cli = cli::FlakeHubPushCli::parse();
cli.instrumentation.setup()?;

// NOTE(cole-h): If --dest-dir is passed, we're intentionally avoiding doing any actual
// networking (i.e. for FlakeHub and GitHub)
if let Some(dest_dir) = &cli.dest_dir.0 {
let local_git_root = cli.resolve_local_git_root()?;
let local_rev_info = revision_info::RevisionInfo::from_git_root(&local_git_root)?;
let git_ctx = git_context::GitContext {
spdx_expression: cli.spdx_expression.0.clone(),
repo_topics: vec![],
revision_info: local_rev_info,
};

let release_version = cli.release_version(&git_ctx)?;
let release_tarball_name = format!("{release_version}.tar.gz");
let release_json_name = format!("{release_version}.json");

let (release_metadata, tarball) =
release_metadata::ReleaseMetadata::new(&cli, &git_ctx, None).await?;

std::fs::create_dir_all(dest_dir)?;

{
let dest_file = dest_dir.join(release_tarball_name);
tracing::info!("Writing tarball to {}", dest_file.display());
std::fs::write(dest_file, tarball.bytes)?;
}

{
let dest_file = dest_dir.join(release_json_name);
tracing::info!("Writing release metadata to {}", dest_file.display());
std::fs::write(dest_file, serde_json::to_string(&release_metadata)?)?;
}

return Ok(ExitCode::SUCCESS);
}

let ctx = PushContext::from_cli_and_env(&mut cli).await?;

let fhclient = FlakeHubClient::new(ctx.flakehub_host, ctx.auth_token)?;

Expand Down
Loading
Loading