BlueGit

golden-age paperdoll-renderer

Files

paperdoll-renderer / tests / release_publish.rs

release_publish.rs

release_publish.rs 4.8 KiB Download Raw
1//! The tag publish step publishes onto the existing tag with BlueGit's
2//! create-only route POST /repos/{owner}/{repo}/releases/{tag}/assets: it
3//! must never call the tag-creating POST .../releases and never send replace.
4
5#![cfg(unix)]
6
7use std::fs;
8use std::os::unix::fs::PermissionsExt;
9use std::path::PathBuf;
10use std::process::Command;
11
12fn repo_root() -> PathBuf {
13 PathBuf::from(env!("CARGO_MANIFEST_DIR"))
14}
15
16fn path_prefix_env(prefix: &std::path::Path) -> std::ffi::OsString {
17 let mut path = std::ffi::OsString::from(prefix);
18 path.push(":");
19 path.push(std::env::var_os("PATH").unwrap_or_default());
20 path
21}
22
23fn install_curl_trap(dir: &std::path::Path) -> PathBuf {
24 let curl = dir.join("curl");
25 fs::write(
26 &curl,
27 "#!/bin/sh\nprintf '%s\\n' \"$*\" >> \"${CURL_TRAP_LOG:?}\"\nprintf 201\nexit 0\n",
28 )
29 .unwrap();
30 let mut permissions = fs::metadata(&curl).unwrap().permissions();
31 permissions.set_mode(0o755);
32 fs::set_permissions(&curl, permissions).unwrap();
33 curl
34}
35
36fn executable_lines(script: &str) -> String {
37 script
38 .lines()
39 .map(str::trim)
40 .filter(|line| !line.is_empty() && !line.starts_with('#'))
41 .collect::<Vec<_>>()
42 .join("\n")
43}
44
45#[test]
46fn tag_publish_uses_only_the_existing_tag_route_without_replace() {
47 let dir = std::env::temp_dir().join(format!("paperdoll-release-trap-{}", std::process::id()));
48 let _ = fs::remove_dir_all(&dir);
49 fs::create_dir_all(&dir).unwrap();
50 let log = dir.join("curl.log");
51 install_curl_trap(&dir);
52
53 let output = Command::new("bash")
54 .arg(repo_root().join("scripts/ci/release.sh"))
55 .env("PATH", path_prefix_env(&dir))
56 .env("CURL_TRAP_LOG", &log)
57 .env("CI_API_URL", "https://git.example.invalid/api/v1")
58 .env("CI_JOB_TOKEN", "bgj_test_token_not_secret")
59 .env("CI_COMMIT_SHA", "0123456789abcdef0123456789abcdef01234567")
60 .env("CI_PROJECT_PATH", "golden-age/paperdoll-renderer")
61 .env("CI_COMMIT_TAG", "v0.1.0")
62 .env_remove("PACKAGE_VERSION")
63 .output()
64 .unwrap();
65
66 let stderr = String::from_utf8_lossy(&output.stderr);
67 let stdout = String::from_utf8_lossy(&output.stdout);
68 assert_eq!(
69 output.status.code(),
70 Some(0),
71 "stdout:\n{stdout}\nstderr:\n{stderr}"
72 );
73 let calls = fs::read_to_string(&log).unwrap();
74 assert_eq!(
75 calls.lines().filter(|l| l.contains("http")).count(),
76 1,
77 "{calls}"
78 );
79 assert!(
80 calls.contains(
81 "https://git.example.invalid/api/v1/repos/golden-age/paperdoll-renderer/releases/v0.1.0/assets"
82 ),
83 "{calls}"
84 );
85 assert!(!calls.contains("replace"), "{calls}");
86 // BlueGit requires the full tag commit (pipeline #582 failed without it).
87 assert!(
88 calls.contains("\"commit\":\"0123456789abcdef0123456789abcdef01234567\""),
89 "{calls}"
90 );
91 assert!(!calls.contains("\"tag\""), "{calls}");
92 for name in [
93 "paperdoll-renderer-v0.1.0-x86_64.AppImage",
94 "paperdoll-renderer-v0.1.0-amd64.deb",
95 "paperdoll-renderer-v0.1.0-x86_64.pkg.tar.zst",
96 "paperdoll-renderer-v0.1.0-windows-x86_64.zip",
97 "paperdoll-renderer-v0.1.0-SHA256SUMS.txt",
98 ] {
99 assert!(calls.contains(name), "{name} missing: {calls}");
100 }
101 let script = fs::read_to_string(repo_root().join("scripts/ci/release.sh")).unwrap();
102 let executable = executable_lines(&script);
103 assert!(
104 !executable.contains("replace"),
105 "executable release script must not send replace:\n{executable}"
106 );
107 let _ = fs::remove_dir_all(&dir);
108}
109
110#[test]
111fn tag_publish_rejects_a_non_semver_tag_before_the_api() {
112 let dir =
113 std::env::temp_dir().join(format!("paperdoll-release-trap-bad-{}", std::process::id()));
114 let _ = fs::remove_dir_all(&dir);
115 fs::create_dir_all(&dir).unwrap();
116 let log = dir.join("curl.log");
117 install_curl_trap(&dir);
118 let output = Command::new("bash")
119 .arg(repo_root().join("scripts/ci/release.sh"))
120 .env("PATH", path_prefix_env(&dir))
121 .env("CURL_TRAP_LOG", &log)
122 .env("CI_API_URL", "https://git.example.invalid/api/v1")
123 .env("CI_JOB_TOKEN", "bgj_test_token_not_secret")
124 .env("CI_COMMIT_SHA", "0123456789abcdef0123456789abcdef01234567")
125 .env("CI_PROJECT_PATH", "golden-age/paperdoll-renderer")
126 .env("CI_COMMIT_TAG", "not-a-version")
127 .env_remove("PACKAGE_VERSION")
128 .output()
129 .unwrap();
130 assert_ne!(output.status.code(), Some(0));
131 assert_ne!(output.status.code(), Some(3));
132 let stderr = String::from_utf8_lossy(&output.stderr);
133 assert!(stderr.contains("package version must be X.Y.Z"), "{stderr}");
134 assert!(!log.exists(), "curl was invoked for an invalid tag");
135 let _ = fs::remove_dir_all(&dir);
136}