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

Basic support for cloning public projects #10

Merged
merged 25 commits into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
87f0596
Allow version for client only, in case server doesn't respond
eikek Jul 3, 2024
690c23d
Get details of a project by namespace/slug or id
eikek Jul 3, 2024
00e5816
Add rudimentary git cloning
eikek Jul 3, 2024
3b6f6b2
Clone sequentially
eikek Jul 4, 2024
d84d2ff
baby steps
eikek Jul 4, 2024
d131249
Cloning async and parallel if possible
eikek Jul 12, 2024
35cd0a2
Write renku config when cloning
eikek Jul 16, 2024
8f6de0d
Write test file to /tmp
eikek Jul 17, 2024
31ae2eb
Fix userdoc cmd that broke due to refactor
eikek Jul 17, 2024
d0b0e7d
Allow a complete (ui) url for cloning
eikek Jul 17, 2024
b0d8d66
Run installer check on main only
eikek Jul 17, 2024
c5d1729
Add version field to config file
eikek Jul 17, 2024
ca6370e
Create api url consistently
eikek Jul 17, 2024
959ca4a
Rename config -> project_config
eikek Jul 17, 2024
632256d
Add code owners file
eikek Jul 17, 2024
fc65139
Parse user supplied urls into reqwest::Url
eikek Jul 17, 2024
1633930
Implement review feedback, part1
eikek Jul 17, 2024
121e851
Remove `as_string` and move impl into Display
eikek Jul 17, 2024
ec55a62
Fix doc strings
eikek Jul 17, 2024
8f90583
Remove last occurence of as_string
eikek Jul 17, 2024
cc024bf
Introduce RenkuUrl type and reorganize a bit
eikek Jul 18, 2024
66f6a2e
Error early when name cannot be derived from repo url
eikek Jul 18, 2024
8171a93
Rename write -> write_out
eikek Jul 18, 2024
9fc7d8d
Lost a change
eikek Jul 18, 2024
c347809
Make a alias 'clone' for 'project clone'
eikek Jul 18, 2024
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
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @SwissDataScienceCenter/renku-python-maintainers @SwissDataScienceCenter/renku-graph-maintainers
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,12 @@ jobs:
command: run
args: --release --features user-doc -- user-doc ./docs

# check installer on main only, as we reach the github api limit too
# quickly
check-installer:
name: "check installer"
runs-on: ${{ matrix.os }}
if: github.ref == 'refs/heads/main'
strategy:
matrix:
os: [macos-latest, ubuntu-latest]
Expand Down
155 changes: 153 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ snafu = { version = "0.8.4" }
tokio = { version = "1", features = ["full"] }
futures = { version = "0.3" }
regex = { version = "1.10.5" }
iso8601-timestamp = { version = "0.2.17" }
toml = { version = "0.8.12" }
git2 = "0.19.0"
url = { version = "2.5.1" }
comrak = { version = "0.24.1", optional = true }

[features]
Expand Down
4 changes: 3 additions & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@

# Additional dev-shell environment variables can be set directly
# MY_CUSTOM_DEVELOPMENT_VAR = "something else";
RENKU_CLI_RENKU_URL = "https://ci-renku-3668.dev.renku.ch";
RENKU_CLI_RENKU_URL = "https://ci-renku-3689.dev.renku.ch";

# Enable mold https://github.com/rui314/mold
CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER = "${pkgs.clang}/bin/clang";
Expand All @@ -186,6 +186,8 @@
# Extra inputs can be added here; cargo and rustc are provided by default.
packages = with pkgs; [
cargo-edit
cargo-expand
tokio-console
fenixToolChain.rust-analyzer
fenixToolChain.rustfmt
];
Expand Down
9 changes: 7 additions & 2 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub mod cmd;
pub mod opts;
pub mod sink;

use self::cmd::project::Error as ProjectError;
use self::cmd::{CmdError, Context};
use self::opts::{MainOpts, SubCommand};
use clap::CommandFactory;
Expand All @@ -18,10 +19,14 @@ pub async fn execute_cmd(opts: MainOpts) -> Result<(), CmdError> {
let mut app = MainOpts::command();
input.print_completions(&mut app).await;
}
SubCommand::Project(input) => input.exec(&ctx).await?,
SubCommand::Project(input) => input.exec(ctx).await?,
SubCommand::Clone(input) => input
.exec(ctx)
.await
.map_err(|source| ProjectError::Clone { source })?,

#[cfg(feature = "user-doc")]
SubCommand::UserDoc(input) => input.exec(&ctx).await?,
SubCommand::UserDoc(input) => input.exec(ctx).await?,
};
Ok(())
}
Expand Down
43 changes: 28 additions & 15 deletions src/cli/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,51 +6,64 @@ pub mod version;

use super::sink::{Error as SinkError, Sink};
use crate::cli::opts::{CommonOpts, ProxySetting};
use crate::data::renku_url::RenkuUrl;
use crate::httpclient::{self, proxy, Client};
use serde::Serialize;
use snafu::{ResultExt, Snafu};

const RENKULAB_IO: &str = "https://renkulab.io";

pub struct Context<'a> {
pub opts: &'a CommonOpts,
pub struct Context {
pub opts: CommonOpts,
pub client: Client,
pub renku_url: String,
}

impl Context<'_> {
impl Context {
pub fn new(opts: &CommonOpts) -> Result<Context, CmdError> {
let base_url = get_renku_url(opts);
let client = Client::new(&base_url, proxy_settings(opts), &None, false)
.context(ContextCreateSnafu)?;
let base_url = get_renku_url(opts)?;
let client =
Client::new(base_url, proxy_settings(opts), None, false).context(ContextCreateSnafu)?;
Ok(Context {
opts,
opts: opts.clone(),
client,
renku_url: base_url,
})
}

/// A short hand for `Sink::write(self.format(), value)`
pub fn renku_url(&self) -> &RenkuUrl {
self.client.base_url()
}

/// A short hand for `Sink::write_out(self.format(), value)`
async fn write_result<A: Sink + Serialize>(&self, value: &A) -> Result<(), SinkError> {
let fmt = self.opts.format;
Sink::write(&fmt, value)
Sink::write_out(&fmt, value)
}

/// A short hand for `Sink::write_err(self.format(), value)`
async fn write_err<A: Sink + Serialize>(&self, value: &A) -> Result<(), SinkError> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thought: I wonder if we should have a write_info and write_err, both going to stderr but formatting output slightly differently? Like it could be INFO: message and ERROR: message. My main motivation is that having write_err in the codebase when writing progress could be a bit confusing, as someone new might think it's writing an actual error, not writing to stderr.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The little difficulty here is that we always need to consider json and human-readable output. So while we can change the output for human-readable, it doesn't look so great for the json variant, or?
The general guideline for the cli part of the codebase (currently) is to only write the actual result to stdout and logging/progress always to stderr.
I also find write and write_err not great… I could also rename write to write_out or similar? so at least they show their relationship better?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renaming it to show the relationship better makes sense.

But just to make sure I understand, actual errors we write to stdout as json if the format is json?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, that at least is the intention or suggestion right now. If the outcome of the command is an error it should go as json to stdout. stderr would be for non-result output, like progress or debug logging (if verbose flag is set). When doing logging, there is just plain text, no json right now.

let fmt = self.opts.format;
Sink::write_err(&fmt, value)
}
}

fn get_renku_url(opts: &CommonOpts) -> String {
fn get_renku_url(opts: &CommonOpts) -> Result<RenkuUrl, CmdError> {
match &opts.renku_url {
Some(u) => {
log::debug!("Use renku url from arguments: {}", u);
u.clone()
Ok(u.clone())
}
None => match std::env::var("RENKU_CLI_RENKU_URL").ok() {
Some(u) => {
log::debug!("Use renku url from env RENKU_CLI_RENKU_URL: {}", u);
u
RenkuUrl::parse(&u).map_err(|e| CmdError::ContextCreate {
source: httpclient::Error::UrlParse { source: e },
})
}
None => {
log::debug!("Use renku url: https://renkulab.io");
RENKULAB_IO.to_string()
RenkuUrl::parse(RENKULAB_IO).map_err(|e| CmdError::ContextCreate {
source: httpclient::Error::UrlParse { source: e },
})
}
},
}
Expand Down
Loading
Loading