Initial Dever 0.0.1
This commit is contained in:
commit
81233d098c
1479 files changed
+163782
No files matched your search
@@ -0,0 +1,220 @@
|
||||
//! 只在测试自己的目录中,用 dev Pod 已安装的绝对路径 Go 工具制作签名 fixture。
|
||||
|
||||
use super::*;
|
||||
use ring::signature::{Ed25519KeyPair, KeyPair};
|
||||
use std::{
|
||||
fs,
|
||||
os::unix::fs::{DirBuilderExt, PermissionsExt},
|
||||
path::{Path, PathBuf},
|
||||
process::Command,
|
||||
};
|
||||
|
||||
pub struct Fixture {
|
||||
pub root: PathBuf,
|
||||
pub signed: SignedResources,
|
||||
pub files: BTreeMap<String, Vec<u8>>,
|
||||
pub descriptor: serde_json::Value,
|
||||
}
|
||||
|
||||
pub fn write(root: &Path, path: &str, bytes: impl AsRef<[u8]>) {
|
||||
let path = root.join(path);
|
||||
fs::create_dir_all(path.parent().unwrap()).unwrap();
|
||||
for directory in path
|
||||
.parent()
|
||||
.unwrap()
|
||||
.ancestors()
|
||||
.take_while(|path| path.starts_with(root))
|
||||
{
|
||||
fs::set_permissions(directory, fs::Permissions::from_mode(0o700)).unwrap();
|
||||
}
|
||||
fs::write(&path, bytes).unwrap();
|
||||
fs::set_permissions(path, fs::Permissions::from_mode(0o600)).unwrap();
|
||||
}
|
||||
|
||||
fn go(root: &Path, arguments: &[&str]) -> String {
|
||||
let result = Command::new("/usr/local/go/bin/go")
|
||||
.args(arguments)
|
||||
.current_dir(root)
|
||||
.env_clear()
|
||||
.env("GOTOOLCHAIN", "local")
|
||||
.env("GOPROXY", "off")
|
||||
.env("GOSUMDB", "off")
|
||||
.env("CGO_ENABLED", "0")
|
||||
.env("GO111MODULE", "off")
|
||||
.env("GOCACHE", root.join("go-cache"))
|
||||
.output()
|
||||
.unwrap();
|
||||
assert!(
|
||||
result.status.success(),
|
||||
"{}",
|
||||
String::from_utf8_lossy(&result.stderr)
|
||||
);
|
||||
String::from_utf8(result.stdout).unwrap()
|
||||
}
|
||||
|
||||
impl Fixture {
|
||||
pub fn new() -> Self {
|
||||
let root = std::env::temp_dir().join(format!(
|
||||
"dever-go-acceptance-{}-{}",
|
||||
std::process::id(),
|
||||
std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_nanos()
|
||||
));
|
||||
fs::DirBuilder::new().mode(0o700).create(&root).unwrap();
|
||||
let version = go(&root, &["version"]);
|
||||
let target = BuildTarget::host().unwrap();
|
||||
let arch = if target == BuildTarget::LinuxX86_64 {
|
||||
"amd64"
|
||||
} else {
|
||||
"arm64"
|
||||
};
|
||||
let version_number = version
|
||||
.split_whitespace()
|
||||
.nth(2)
|
||||
.unwrap()
|
||||
.strip_prefix("go")
|
||||
.unwrap();
|
||||
write(&root, "selector.go", include_bytes!("selector.go"));
|
||||
go(
|
||||
&root,
|
||||
&["build", "-trimpath", "-o", "selector", "selector.go"],
|
||||
);
|
||||
let mut files = BTreeMap::new();
|
||||
files.insert(
|
||||
"bin/analyze".into(),
|
||||
fs::read(root.join("selector")).unwrap(),
|
||||
);
|
||||
for tool in ["compile", "link"] {
|
||||
files.insert(
|
||||
format!("bin/{tool}"),
|
||||
fs::read(format!("/usr/local/go/pkg/tool/linux_{arch}/{tool}")).unwrap(),
|
||||
);
|
||||
}
|
||||
let exports = go(
|
||||
&root,
|
||||
&[
|
||||
"list",
|
||||
"-deps",
|
||||
"-export",
|
||||
"-f",
|
||||
"{{if .Export}}{{.ImportPath}}={{.Export}}{{end}}",
|
||||
"bytes",
|
||||
"context",
|
||||
"encoding/binary",
|
||||
"encoding/json",
|
||||
"errors",
|
||||
"fmt",
|
||||
"io",
|
||||
"math",
|
||||
"os",
|
||||
"regexp",
|
||||
"sort",
|
||||
"strconv",
|
||||
"strings",
|
||||
"time",
|
||||
"unicode/utf8",
|
||||
"embed",
|
||||
],
|
||||
);
|
||||
let mut cfg = String::new();
|
||||
for line in exports.lines().filter(|line| !line.is_empty()) {
|
||||
let (name, source) = line.split_once('=').unwrap();
|
||||
let path = format!("stdlib/{name}.a");
|
||||
cfg.push_str(&format!("packagefile {name}={path}\n"));
|
||||
files.insert(path, fs::read(source).unwrap());
|
||||
}
|
||||
files.insert("stdlib/importcfg".into(), cfg.into_bytes());
|
||||
let descriptor = serde_json::json!({"host":target.name(), "compiler":"bin/compile", "linker":"bin/link", "analyzer":"bin/analyze",
|
||||
"stdlib_importcfg":"stdlib/importcfg", "goos":"linux", "goarch":arch, "go_version":version.trim()});
|
||||
files.insert("dever-runtime.json".into(), serde_json::to_vec(&serde_json::json!({"format":"dever-worker-runtime-v1", "ecosystem":"go", "target":target.name(),
|
||||
"executable":null, "arguments":[], "build":descriptor, "python_markers":null, "python_wheel_tags":[]})).unwrap());
|
||||
let archive = archive(&files);
|
||||
let metadata = serde_json::to_vec(&serde_json::json!({"format":"dever-registry-runtime-v1", "runtime":{"pack":{"name":"go", "version":version_number,
|
||||
"sha256":crate::compiler::project::dependency::digest(&archive)}, "target":target.name(), "python_markers":null, "python_wheel_tags":[]}})).unwrap();
|
||||
let loader = if arch == "amd64" {
|
||||
"ld-linux-x86-64.so.2"
|
||||
} else {
|
||||
"ld-linux-aarch64.so.1"
|
||||
};
|
||||
let loader_source = if arch == "amd64" {
|
||||
"/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2"
|
||||
} else {
|
||||
"/lib/aarch64-linux-gnu/ld-linux-aarch64.so.1"
|
||||
};
|
||||
let artifacts = BTreeMap::from([
|
||||
(
|
||||
format!("runtime/go/{}/runtime.pack", target.name()),
|
||||
archive,
|
||||
),
|
||||
(
|
||||
format!("runtime/go/{}/manifest.json", target.name()),
|
||||
metadata,
|
||||
),
|
||||
(
|
||||
format!("process-runtime/{}/lib/{loader}", target.name()),
|
||||
fs::read(loader_source).unwrap(),
|
||||
),
|
||||
(
|
||||
"sdk/go/component.go".into(),
|
||||
fs::read(Path::new(env!("CARGO_MANIFEST_DIR")).join("../sdk/go/component.go"))
|
||||
.unwrap(),
|
||||
),
|
||||
]);
|
||||
let signed = sign(&root.join("installation"), &artifacts);
|
||||
Self {
|
||||
root,
|
||||
signed,
|
||||
files,
|
||||
descriptor,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn archive(files: &BTreeMap<String, Vec<u8>>) -> Vec<u8> {
|
||||
let gzip = flate2::write::GzEncoder::new(Vec::new(), flate2::Compression::fast());
|
||||
let mut tar = tar::Builder::new(gzip);
|
||||
for (name, bytes) in files {
|
||||
let mut header = tar::Header::new_gnu();
|
||||
header.set_size(bytes.len() as u64);
|
||||
header.set_mode(0o644);
|
||||
header.set_cksum();
|
||||
tar.append_data(&mut header, name, bytes.as_slice())
|
||||
.unwrap();
|
||||
}
|
||||
tar.into_inner().unwrap().finish().unwrap()
|
||||
}
|
||||
|
||||
pub fn sign(root: &Path, artifacts: &BTreeMap<String, Vec<u8>>) -> SignedResources {
|
||||
let key = Ed25519KeyPair::from_seed_unchecked(&[93; 32]).unwrap();
|
||||
let hex = |bytes: &[u8]| {
|
||||
bytes
|
||||
.iter()
|
||||
.map(|byte| format!("{byte:02x}"))
|
||||
.collect::<String>()
|
||||
};
|
||||
write(
|
||||
root,
|
||||
"state/trusted-release-key",
|
||||
hex(key.public_key().as_ref()),
|
||||
);
|
||||
let entries = artifacts.iter().map(|(path, bytes)| {
|
||||
write(root, &format!("versions/0.0.1/{path}"), bytes);
|
||||
serde_json::json!({"path":path, "bytes":bytes.len(), "sha256":crate::compiler::project::dependency::digest(bytes)})
|
||||
}).collect::<Vec<_>>();
|
||||
let manifest = serde_json::to_vec(&serde_json::json!({"format":"dever-release-v2", "version":"0.0.1", "platform":BuildTarget::host().unwrap().name(), "artifacts":entries, "extensions":[]})).unwrap();
|
||||
write(root, "versions/0.0.1/manifest.json", &manifest);
|
||||
write(
|
||||
root,
|
||||
"versions/0.0.1/manifest.sig",
|
||||
hex(key.sign(&manifest).as_ref()),
|
||||
);
|
||||
SignedResources::load(root, "0.0.1").unwrap()
|
||||
}
|
||||
|
||||
impl Drop for Fixture {
|
||||
fn drop(&mut self) {
|
||||
fs::remove_dir_all(&self.root).unwrap();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user