Initial stabilization #1

Merged
dzu merged 22 commits from stabilize-v1 into main 2026-02-21 04:54:42 +01:00
3 changed files with 1264 additions and 68 deletions
Showing only changes of commit f83df3c874 - Show all commits

ench: cache entry reservation
All checks were successful
Build and update the action / build-and-upload (push) Successful in 3m57s

Artem Diachenko 2026-02-17 12:41:15 +00:00

1100
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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:?}");
}