add attic push functionality
This commit is contained in:
parent
9ca574cb94
commit
f982e37fe5
8 changed files with 175 additions and 58 deletions
2
.envrc
2
.envrc
|
|
@ -1 +1 @@
|
||||||
use nix
|
use flake
|
||||||
|
|
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,2 +1,3 @@
|
||||||
/target
|
/target
|
||||||
/result
|
/result
|
||||||
|
.direnv
|
||||||
|
|
|
||||||
23
flake.lock
generated
23
flake.lock
generated
|
|
@ -18,7 +18,28 @@
|
||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": "nixpkgs"
|
"nixpkgs": "nixpkgs",
|
||||||
|
"rust-overlay": "rust-overlay"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rust-overlay": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1760063676,
|
||||||
|
"narHash": "sha256-s5Fjh43skH2L+avOGioLmEHoYZffDbg3abV5h0gjeew=",
|
||||||
|
"owner": "oxalica",
|
||||||
|
"repo": "rust-overlay",
|
||||||
|
"rev": "897deed0923cc5a1d560c5176abe0d172ec9716d",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "oxalica",
|
||||||
|
"repo": "rust-overlay",
|
||||||
|
"type": "github"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
95
flake.nix
95
flake.nix
|
|
@ -1,34 +1,47 @@
|
||||||
{
|
{
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||||
|
rust-overlay = {
|
||||||
|
url = "github:oxalica/rust-overlay";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
outputs = {
|
outputs =
|
||||||
nixpkgs,
|
{ nixpkgs
|
||||||
self,
|
, rust-overlay
|
||||||
}: let
|
, self
|
||||||
forAllSystems = fn:
|
,
|
||||||
builtins.foldl' (attrs: system: let
|
}:
|
||||||
outputs = fn system;
|
let
|
||||||
outputNames = builtins.attrNames outputs;
|
forAllSystems = fn:
|
||||||
in
|
builtins.foldl'
|
||||||
builtins.foldl' (attrs: outName: let
|
(attrs: system:
|
||||||
existing = attrs.${outName} or {};
|
let
|
||||||
new = existing // {${system} = outputs.${outName};};
|
outputs = fn system;
|
||||||
in
|
outputNames = builtins.attrNames outputs;
|
||||||
attrs // {${outName} = new;})
|
in
|
||||||
attrs
|
builtins.foldl'
|
||||||
outputNames) {} ["x86_64-linux" "aarch64-linux"];
|
(attrs: outName:
|
||||||
in
|
let
|
||||||
|
existing = attrs.${outName} or { };
|
||||||
|
new = existing // { ${system} = outputs.${outName}; };
|
||||||
|
in
|
||||||
|
attrs // { ${outName} = new; })
|
||||||
|
attrs
|
||||||
|
outputNames)
|
||||||
|
{ } [ "x86_64-linux" "aarch64-linux" ];
|
||||||
|
in
|
||||||
{
|
{
|
||||||
overlays.default = final: prev: {
|
overlays.default = final: prev: {
|
||||||
nix-ci = final.lib.flip final.callPackage {} ({
|
nix-ci = final.lib.flip final.callPackage { } ({ rustPlatform
|
||||||
rustPlatform,
|
, lib
|
||||||
lib,
|
, makeWrapper
|
||||||
makeWrapper,
|
, nix-eval-jobs
|
||||||
nix-eval-jobs,
|
,
|
||||||
}: let
|
}:
|
||||||
cargoToml = builtins.fromTOML (builtins.readFile ./Cargo.toml);
|
let
|
||||||
in
|
cargoToml = builtins.fromTOML (builtins.readFile ./Cargo.toml);
|
||||||
|
in
|
||||||
rustPlatform.buildRustPackage {
|
rustPlatform.buildRustPackage {
|
||||||
pname = cargoToml.package.name;
|
pname = cargoToml.package.name;
|
||||||
version = cargoToml.package.version;
|
version = cargoToml.package.version;
|
||||||
|
|
@ -40,7 +53,7 @@
|
||||||
./Cargo.lock
|
./Cargo.lock
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
nativeBuildInputs = [makeWrapper];
|
nativeBuildInputs = [ makeWrapper ];
|
||||||
cargoLock.lockFile = ./Cargo.lock;
|
cargoLock.lockFile = ./Cargo.lock;
|
||||||
preFixup = ''
|
preFixup = ''
|
||||||
wrapProgram "$out/bin/nix-ci" \
|
wrapProgram "$out/bin/nix-ci" \
|
||||||
|
|
@ -49,13 +62,35 @@
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// forAllSystems (system: let
|
// forAllSystems (system:
|
||||||
|
let
|
||||||
pkgs = import nixpkgs {
|
pkgs = import nixpkgs {
|
||||||
inherit system;
|
inherit system;
|
||||||
overlays = [self.overlays.default];
|
overlays = [
|
||||||
|
self.overlays.default
|
||||||
|
rust-overlay.overlays.default
|
||||||
|
|
||||||
|
|
||||||
|
(final: prev: {
|
||||||
|
inherit (prev.lixPackageSets.stable)
|
||||||
|
nixpkgs-review
|
||||||
|
nix-eval-jobs
|
||||||
|
nix-fast-build
|
||||||
|
colmena;
|
||||||
|
})
|
||||||
|
];
|
||||||
|
};
|
||||||
|
rust = pkgs.rust-bin.stable.latest.default.override {
|
||||||
|
extensions = [
|
||||||
|
"rust-src" # for rust-analyzer
|
||||||
|
"rust-analyzer"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
devShells.default = pkgs.mkShell {
|
||||||
|
nativeBuildInputs = [ pkgs.nix-eval-jobs rust pkgs.attic-client ];
|
||||||
};
|
};
|
||||||
in {
|
|
||||||
devShells.default = import ./shell.nix {inherit pkgs;};
|
|
||||||
packages = {
|
packages = {
|
||||||
default = pkgs.nix-ci;
|
default = pkgs.nix-ci;
|
||||||
nix-ci = pkgs.nix-ci;
|
nix-ci = pkgs.nix-ci;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
{pkgs ? import <nixpkgs> {}}:
|
|
||||||
pkgs.mkShell {
|
|
||||||
nativeBuildInputs = with pkgs; [nix-eval-jobs];
|
|
||||||
}
|
|
||||||
|
|
@ -17,6 +17,9 @@ pub struct Options {
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
/// store uri where build outputs will be uploaded to
|
/// store uri where build outputs will be uploaded to
|
||||||
pub copy_to: Option<String>,
|
pub copy_to: Option<String>,
|
||||||
|
#[arg(long)]
|
||||||
|
/// attic store where build outputs will be uploaded to
|
||||||
|
pub copy_to_attic: Option<String>,
|
||||||
|
|
||||||
#[arg(long, default_value = "4")]
|
#[arg(long, default_value = "4")]
|
||||||
/// maximum number of evaluation workers
|
/// maximum number of evaluation workers
|
||||||
|
|
|
||||||
91
src/copy.rs
91
src/copy.rs
|
|
@ -51,34 +51,57 @@ pub async fn copy_loop(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let Some(copy_to) = &opts.copy_to else {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
for store_path in &valid_paths {
|
for store_path in &valid_paths {
|
||||||
if paths_copied.contains(store_path) {
|
if paths_copied.contains(store_path) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
paths_copied.push(store_path.clone());
|
paths_copied.push(store_path.clone());
|
||||||
match copy_path(store_path, copy_to).await {
|
if let Some(copy_to) = &opts.copy_to {
|
||||||
Ok(()) => {
|
match copy_path(store_path, copy_to).await {
|
||||||
let _ = result_tx
|
Ok(()) => {
|
||||||
.send(NixCiResult {
|
let _ = result_tx
|
||||||
r#type: NixCiResultType::Copy,
|
.send(NixCiResult {
|
||||||
path: store_path.clone(),
|
r#type: NixCiResultType::Copy,
|
||||||
success: true,
|
path: store_path.clone(),
|
||||||
})
|
success: true,
|
||||||
.await;
|
})
|
||||||
tracing::info!("copied path {}", store_path);
|
.await;
|
||||||
|
tracing::info!("copied path {}", store_path);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
let _ = result_tx
|
||||||
|
.send(NixCiResult {
|
||||||
|
r#type: NixCiResultType::Copy,
|
||||||
|
path: store_path.clone(),
|
||||||
|
success: false,
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
tracing::error!("failed to copy path {}: {}", store_path, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
}
|
||||||
let _ = result_tx
|
if let Some(copy_to_attic) = &opts.copy_to_attic {
|
||||||
.send(NixCiResult {
|
match copy_path_attic(store_path, copy_to_attic).await {
|
||||||
r#type: NixCiResultType::Copy,
|
Ok(()) => {
|
||||||
path: store_path.clone(),
|
let _ = result_tx
|
||||||
success: false,
|
.send(NixCiResult {
|
||||||
})
|
r#type: NixCiResultType::Copy,
|
||||||
.await;
|
path: store_path.clone(),
|
||||||
tracing::error!("failed to copy path {}: {}", store_path, e);
|
success: true,
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
tracing::info!("copied path {}", store_path);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
let _ = result_tx
|
||||||
|
.send(NixCiResult {
|
||||||
|
r#type: NixCiResultType::Copy,
|
||||||
|
path: store_path.clone(),
|
||||||
|
success: false,
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
tracing::error!("failed to copy path {}: {}", store_path, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -141,6 +164,30 @@ async fn check_path_validity(store_path: &str) -> anyhow::Result<bool> {
|
||||||
Ok(cmd.status.success())
|
Ok(cmd.status.success())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn copy_path_attic(store_path: &str, attic_store: &str) -> anyhow::Result<()> {
|
||||||
|
let mut cmd = WrappedChild::new(
|
||||||
|
Command::new("attic").args(&["push", attic_store, store_path]),
|
||||||
|
Some(format!("attic push {} {}", attic_store, store_path)),
|
||||||
|
)?;
|
||||||
|
loop {
|
||||||
|
match cmd.next_line().await? {
|
||||||
|
ChildOutput::Finished => break,
|
||||||
|
ChildOutput::Stderr(line) | ChildOutput::Stdout(line) => {
|
||||||
|
tracing::info!("{}", line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let exit_status = cmd.exit_status().unwrap();
|
||||||
|
if exit_status.success() {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(anyhow::anyhow!(
|
||||||
|
"nix copy exited with non-success {}",
|
||||||
|
exit_status
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn copy_path(store_path: &str, copy_to: &str) -> anyhow::Result<()> {
|
async fn copy_path(store_path: &str, copy_to: &str) -> anyhow::Result<()> {
|
||||||
let mut cmd = WrappedChild::new(
|
let mut cmd = WrappedChild::new(
|
||||||
Command::new("nix").args(&["copy", "--to", copy_to, store_path]),
|
Command::new("nix").args(&["copy", "--to", copy_to, store_path]),
|
||||||
|
|
|
||||||
14
src/main.rs
14
src/main.rs
|
|
@ -63,6 +63,20 @@ async fn main() -> anyhow::Result<()> {
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Some(store) = &opts.copy_to_attic {
|
||||||
|
let cmd = Command::new("attic")
|
||||||
|
.args(&["cache", "info", store])
|
||||||
|
.output()
|
||||||
|
.await?;
|
||||||
|
if !cmd.status.success() {
|
||||||
|
tracing::error!(
|
||||||
|
"{:?} is not a valid attic store: {}",
|
||||||
|
store,
|
||||||
|
String::from_utf8_lossy(&cmd.stderr),
|
||||||
|
);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tracing::debug!("running with options {:?}", opts);
|
tracing::debug!("running with options {:?}", opts);
|
||||||
let opts = Arc::new(opts);
|
let opts = Arc::new(opts);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue