Initial stabilization #1
3 changed files with 1264 additions and 68 deletions
commit
f83df3c874
1100
Cargo.lock
generated
1100
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
19
Cargo.toml
19
Cargo.toml
|
|
@ -5,16 +5,21 @@ edition = "2024"
|
|||
|
||||
[dependencies]
|
||||
anode = { git = "https://git.dzuchun.ing/dzu/anode.git", version = "0.1.0" }
|
||||
anyhow = "1.0.101"
|
||||
flate2 = "1.1.9"
|
||||
isahc = { version = "1.7.2", features = ["static-ssl", "static-curl"] }
|
||||
secrecy = "0.10.3"
|
||||
serde_json = "1.0.149"
|
||||
tar = "0.4.44"
|
||||
thiserror = "2.0.18"
|
||||
|
||||
[build-dependencies]
|
||||
anode-build = { git = "https://git.dzuchun.ing/dzu/anode.git", version = "0.1.0" }
|
||||
|
||||
[profile.release]
|
||||
opt-level = "s"
|
||||
lto = true
|
||||
codegen-units = 1
|
||||
strip = true
|
||||
panic = "abort"
|
||||
incremental = false
|
||||
# [profile.release]
|
||||
# opt-level = "s"
|
||||
# lto = true
|
||||
# codegen-units = 1
|
||||
# strip = true
|
||||
# panic = "abort"
|
||||
# incremental = false
|
||||
|
|
|
|||
97
src/main.rs
97
src/main.rs
|
|
@ -1,6 +1,15 @@
|
|||
use std::{ffi::OsString, path::PathBuf, str::FromStr, string::FromUtf8Error};
|
||||
|
||||
use secrecy::SecretString;
|
||||
use anyhow::{Context, Result, bail};
|
||||
use flate2::{Compression, GzBuilder};
|
||||
use isahc::{
|
||||
HttpClient, HttpClientBuilder, Request,
|
||||
auth::{Authentication, Credentials},
|
||||
config::Configurable,
|
||||
http::{Method, StatusCode, Uri},
|
||||
};
|
||||
use secrecy::{ExposeSecret, SecretString};
|
||||
use tar::{Archive, Builder, HeaderMode};
|
||||
|
||||
fn paths_parser(input: OsString) -> Result<Vec<PathBuf>, FromUtf8Error> {
|
||||
let input = String::from_utf8(input.into_encoded_bytes())?;
|
||||
|
|
@ -56,6 +65,9 @@ struct Input {
|
|||
/// Must be in UTF-8
|
||||
#[parser(key_parser)]
|
||||
key: CacheKey,
|
||||
/// A server url to upload the cache to
|
||||
#[default_str("${{ forgejo.api_url }}")]
|
||||
base_url: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
|
|
@ -73,8 +85,87 @@ fn actions_token() -> Result<SecretString, ActionsTokenError> {
|
|||
Ok(SecretString::new(str.into_boxed_str()))
|
||||
}
|
||||
|
||||
struct Client {
|
||||
http_client: HttpClient,
|
||||
base_url: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct CacheId(u64);
|
||||
|
||||
impl Client {
|
||||
fn reserve(&self, key: &CacheKey, cacheSize: usize) -> Result<CacheId> {
|
||||
let request = Request::builder()
|
||||
.uri(format!(
|
||||
"{}/_apis/artifactcache/reverveCache",
|
||||
self.base_url
|
||||
))
|
||||
.method(Method::POST)
|
||||
.body(
|
||||
serde_json::json! {{
|
||||
"key": &key.0,
|
||||
"version": "0",
|
||||
"cacheSize": cacheSize,
|
||||
}}
|
||||
.to_string(),
|
||||
)
|
||||
.context("building the request")?;
|
||||
let response = self
|
||||
.http_client
|
||||
.send(request)
|
||||
.context("sending the request")?;
|
||||
let status = response.status();
|
||||
if status != StatusCode::OK {
|
||||
bail!(
|
||||
"Failed reserving a cache (status {status}): {:?}",
|
||||
response.body()
|
||||
);
|
||||
}
|
||||
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let input = Input::get();
|
||||
// parse inputs
|
||||
let Input {
|
||||
path,
|
||||
key,
|
||||
base_url,
|
||||
} = Input::get();
|
||||
let actions_token = actions_token().unwrap();
|
||||
println!("Inputs: {input:#?}, token: {actions_token:?}");
|
||||
|
||||
// set up http client
|
||||
let http_client = HttpClientBuilder::new()
|
||||
.authentication(Authentication::basic())
|
||||
.credentials(Credentials::new("Bearer", actions_token.expose_secret()))
|
||||
.build()
|
||||
.unwrap();
|
||||
let client = Client {
|
||||
http_client,
|
||||
base_url,
|
||||
};
|
||||
|
||||
// collect and compress the cached files
|
||||
let mut output = Vec::<u8>::with_capacity(1024 * 1024); // assume large cache size
|
||||
let out_comp = GzBuilder::new().write(&mut output, Compression::best());
|
||||
{
|
||||
let mut archive = Builder::new(out_comp);
|
||||
archive.mode(HeaderMode::Complete);
|
||||
archive.follow_symlinks(false);
|
||||
for path in path {
|
||||
if path.is_dir() {
|
||||
// we actually want to write out all the directory contents
|
||||
archive.append_dir_all("", path).unwrap();
|
||||
} else if path.is_file() {
|
||||
// rest of the file types are handled by the existing inner code
|
||||
archive.append_path(path).unwrap();
|
||||
}
|
||||
}
|
||||
archive.finish().unwrap();
|
||||
}
|
||||
|
||||
let cache_id = client.reserve(&key, output.len()).unwrap();
|
||||
|
||||
println!("Reserved cache with id {cache_id:?}");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue