Initial stabilization #1
4 changed files with 1347 additions and 96 deletions
26
.forgejo/workflows/build-action.yml
Normal file
26
.forgejo/workflows/build-action.yml
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
name: Build and update the action
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- dev
|
||||
|
||||
jobs:
|
||||
build-and-upload:
|
||||
runs-on: docker
|
||||
steps:
|
||||
- name: Build and update the action
|
||||
uses: https://git.dzuchun.ing/actions/anode-build@main
|
||||
with:
|
||||
src-repository: https://git.dzuchun.ing/actions/cache-save-src.git
|
||||
src-ref: ${{ forgejo.ref_name }}
|
||||
src-token: ${{ secrets.GIT_TOKEN }}
|
||||
dst-repository: https://git.dzuchun.ing/actions/cache-save.git
|
||||
dst-ref: ${{ forgejo.ref_name }}
|
||||
dst-token: ${{ secrets.GIT_TOKEN }}
|
||||
dst-email: forgejo-actions@dzuchun.ing
|
||||
opt-release: ${{ forgejo.ref_name == 'main' }}
|
||||
opt-build-std: ${{ forgejo.ref_name == 'main' }}
|
||||
opt-upx: ${{ forgejo.ref_name == 'main' }}
|
||||
1216
Cargo.lock
generated
1216
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
20
Cargo.toml
20
Cargo.toml
|
|
@ -4,11 +4,23 @@ version = "0.1.0"
|
|||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
anode = { git = "https://git.dzuchun.ing/dzu/anode.git", version = "0.1.0" }
|
||||
thiserror = "2.0.18"
|
||||
anyhow = "1.0.101"
|
||||
flate2 = "1.1.9"
|
||||
secrecy = "0.10.3"
|
||||
tar = "0.4.44"
|
||||
tracing = { version = "0.1.44", features = ["attributes"] }
|
||||
|
||||
[build-dependencies]
|
||||
anode-build = { git = "https://git.dzuchun.ing/dzu/anode.git", version = "0.1.0" }
|
||||
[dependencies.anode]
|
||||
git = "https://git.dzuchun.ing/dzu/anode.git"
|
||||
rev = "98addf4d54ae16c21979a1dae63d17738b3a277b"
|
||||
|
||||
[dependencies.anode-cache-common]
|
||||
git = "https://git.dzuchun.ing/actions/cache-common-src.git"
|
||||
rev = "5656a3ff6f58a48e3365c221fb2102918db6c284"
|
||||
|
||||
[build-dependencies.anode-build]
|
||||
git = "https://git.dzuchun.ing/dzu/anode.git"
|
||||
rev = "98addf4d54ae16c21979a1dae63d17738b3a277b"
|
||||
|
||||
[profile.release]
|
||||
opt-level = "s"
|
||||
|
|
|
|||
103
src/main.rs
103
src/main.rs
|
|
@ -1,43 +1,11 @@
|
|||
use std::{ffi::OsString, path::PathBuf, str::FromStr, string::FromUtf8Error};
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn paths_parser(input: OsString) -> Result<Vec<PathBuf>, FromUtf8Error> {
|
||||
let input = String::from_utf8(input.into_encoded_bytes())?;
|
||||
let mut paths = Vec::new();
|
||||
for path in input.split('\n') {
|
||||
paths.push(match PathBuf::from_str(path) {
|
||||
Ok(ok) => ok,
|
||||
});
|
||||
}
|
||||
Ok(paths)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct CacheKey(String);
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
enum CacheKeyError {
|
||||
#[error(transparent)]
|
||||
Utf8(#[from] FromUtf8Error),
|
||||
#[error("Cache key is at most 512 characters long. {len} characters long key provided")]
|
||||
Length { len: usize },
|
||||
#[error("Cache key cannot contain commas. Comma found at offset {offset}")]
|
||||
Comma { offset: usize },
|
||||
}
|
||||
|
||||
fn key_parser(input: OsString) -> Result<CacheKey, CacheKeyError> {
|
||||
let input = String::from_utf8(input.into_encoded_bytes())?;
|
||||
let mut len = 0;
|
||||
for (offset, ch) in input.char_indices() {
|
||||
if ch == ',' {
|
||||
return Err(CacheKeyError::Comma { offset });
|
||||
}
|
||||
len += 1;
|
||||
}
|
||||
if len > 512 {
|
||||
return Err(CacheKeyError::Length { len });
|
||||
}
|
||||
Ok(CacheKey(input))
|
||||
}
|
||||
use anode_cache_common::{CacheKey, Client, actions_token, key_parser, paths_parser};
|
||||
use anyhow::{Context, Result};
|
||||
use flate2::{Compression, GzBuilder};
|
||||
use secrecy::ExposeSecret;
|
||||
use tar::{Builder, HeaderMode};
|
||||
use tracing::{debug, info_span, warn};
|
||||
|
||||
#[derive(Debug, anode::Input)]
|
||||
#[name = "Cache save"]
|
||||
|
|
@ -54,9 +22,60 @@ struct Input {
|
|||
/// Must be in UTF-8
|
||||
#[parser(key_parser)]
|
||||
key: CacheKey,
|
||||
/// If the debug log should be printed
|
||||
///
|
||||
/// If omitted, defined by compiler settings (print debug if `debug_assertions` is enabled)
|
||||
debug: Option<bool>,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let input = Input::get();
|
||||
println!("Inputs: {input:#?}");
|
||||
fn main() -> Result<()> {
|
||||
// parse inputs
|
||||
let Input { path, key, debug } = Input::get();
|
||||
anode_cache_common::setup_logger(debug.unwrap_or(cfg!(debug_assertions)));
|
||||
|
||||
let actions_token = actions_token().context("reading actions token")?;
|
||||
|
||||
let cache_url = std::env::var("ACTIONS_CACHE_URL").context("reading action cache url")?;
|
||||
|
||||
// set up http client
|
||||
let client = Client::new(actions_token.expose_secret(), cache_url)
|
||||
.context("intializing cache client")?;
|
||||
debug!("Cache client initialized");
|
||||
|
||||
// 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);
|
||||
debug!(paths = ?path);
|
||||
for path in path {
|
||||
let _span = info_span!("cache-entry");
|
||||
let _span = _span.enter();
|
||||
if !path.exists() {
|
||||
warn!("Path does not exist, and will not be cached");
|
||||
continue;
|
||||
}
|
||||
if path.is_dir() {
|
||||
debug!("Caching directory");
|
||||
// we actually want to write out all the directory contents
|
||||
archive.append_dir_all(&path, &path).unwrap();
|
||||
} else if path.is_file() {
|
||||
debug!("Caching a file");
|
||||
// rest of the file types are handled by the existing inner code
|
||||
archive.append_path(path).unwrap();
|
||||
} else {
|
||||
warn!("Path is neither directory, nor a file and will not be cached");
|
||||
}
|
||||
}
|
||||
archive.finish().unwrap();
|
||||
}
|
||||
debug!("Cache archive cleated");
|
||||
|
||||
client
|
||||
.save_cache(&key, output)
|
||||
.context("saving the cache")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue