From b6615146a4feaa096f086b747732f0ba2dc4df5c Mon Sep 17 00:00:00 2001 From: Graham Christensen Date: Tue, 24 Sep 2024 09:41:51 -0400 Subject: [PATCH 01/10] Update macos, use bigger hardware --- .github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index b7ea348..b2d2e88 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -59,7 +59,7 @@ jobs: - nix-system: aarch64-darwin runner: macos-latest-xlarge - nix-system: x86_64-darwin - runner: macos-12 + runner: macos-13-large steps: - uses: actions/checkout@v3 From e850d85287076dc5e330c87c7b00ebcc03fa29bb Mon Sep 17 00:00:00 2001 From: Graham Christensen Date: Tue, 24 Sep 2024 10:53:41 -0400 Subject: [PATCH 02/10] Add more outputs suitable for deployment pipelines --- README.md | 8 ++++++-- src/main.rs | 28 +++++++++++++++++++++------- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index d33033e..110edd8 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,12 @@ Although the `flakehub-push` Action requires little configuration, you may benef ## Integration -This action sets the `flakeref` output to the exact name and version that was published. -The flake reference can be used in subsequent steps or workflows as part of a deployment process. +This action sets outputs for integrating into CD pipelines: + +- `flake_name` Name of the flake. Example: `DeterminateSystems/flakehub-push` +- `flake_version` Name of the flake. Example: `0.1.99+rev-2075013a3f3544d45a96f4b35df4ed03cd53779c` +- `flakeref_descriptive` A loose reference to this release. Depending on this reference will require at least this version, and will also resolve to newer releases. This output is not sufficient for deployment pipelines, use `flake_exact` instead. Example: `DeterminateSystems/flakehub-push/0.1.99+rev-2075013a3f3544d45a96f4b35df4ed03cd53779c` +- `flake_exact` A precise reference that always resolves to this to this exact release. Example: `DeterminateSystems/flakehub-push/=0.1.99+rev-2075013a3f3544d45a96f4b35df4ed03cd53779c` ## More Information diff --git a/src/main.rs b/src/main.rs index 0ef29b7..5185dd2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -182,13 +182,27 @@ async fn execute() -> Result { ctx.release_version ); - if let Err(e) = github_actions::set_output( - "flakeref", - &format!("{}/{}", ctx.upload_name, ctx.release_version), - ) - .await - { - tracing::warn!("Failed to set the `flakeref` output: {}", e); + let outputs = [ + ("flake_name", &ctx.upload_name), + ("flake_version", &ctx.release_version), + ( + "flakeref_descriptive", + &format!("{}/{}", ctx.upload_name, ctx.release_version), + ), + ( + "flakeref_exact", + &format!("{}/={}", ctx.upload_name, ctx.release_version), + ), + ]; + for (output_name, value) in outputs.into_iter() { + if let Err(e) = github_actions::set_output(output_name, value).await { + tracing::warn!( + "Failed to set the `{}` output to {}: {}", + output_name, + value, + e + ); + } } Ok(ExitCode::SUCCESS) From 2b908f740d9a59882ecef9e0784bff95bb780727 Mon Sep 17 00:00:00 2001 From: Graham Christensen Date: Tue, 24 Sep 2024 11:36:16 -0400 Subject: [PATCH 03/10] escape outputs --- Cargo.toml | 2 +- src/github_actions.rs | 24 +++++++++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1642d44..d215b35 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,7 @@ tracing-error = { version = "0.2.0", default-features = false, features = ["trac tracing-subscriber = { version = "0.3.15", default-features = false, features = [ "std", "registry", "fmt", "json", "ansi", "env-filter" ] } github-actions-oidc-claims = "0.3.0" spdx = "0.10.2" -uuid = { version = "1.4.0", features = ["serde", "v7", "rand", "std"] } +uuid = { version = "1.4.0", features = ["serde", "v4", "v7", "rand", "std"] } semver = { version = "1.0.18", features = ["serde"] } thiserror = "1.0.56" url = { version = "2.5.0", features = ["serde"] } diff --git a/src/github_actions.rs b/src/github_actions.rs index 6d64146..040c344 100644 --- a/src/github_actions.rs +++ b/src/github_actions.rs @@ -10,6 +10,12 @@ pub(crate) enum Error { #[error("Writing to {0:?}: {1}")] WriteFile(std::ffi::OsString, std::io::Error), + + #[error("Key contains delimiter")] + KeyContainsDelimiter, + + #[error("Value contains delimiter")] + ValueContainsDelimiter, } pub(crate) async fn set_output<'a>(name: &'a str, value: &'a str) -> Result<(), Error> { @@ -23,9 +29,25 @@ pub(crate) async fn set_output<'a>(name: &'a str, value: &'a str) -> Result<(), .await .map_err(|e| Error::OpenFile(output_path.clone(), e))?; - fh.write_all(format!("{}={}\n", name, value).as_bytes()) + fh.write_all(escape_key_value(name, value)?.as_bytes()) .await .map_err(|e| Error::WriteFile(output_path, e))?; Ok(()) } + +fn escape_key_value<'a>(key: &'a str, value: &'a str) -> Result { + // see: https://github.com/actions/toolkit/blob/6dd369c0e648ed58d0ead326cf2426906ea86401/packages/core/src/file-command.ts#L27-L47 + let delimiter = format!("ghadelimiter_{}", uuid::Uuid::new_v4()); + let eol = '\n'; + + if key.contains(&delimiter) { + return Err(Error::KeyContainsDelimiter); + } + + if value.contains(&delimiter) { + return Err(Error::ValueContainsDelimiter); + } + + Ok(format!("{key}<<{delimiter}{eol}{value}{eol}{delimiter}")) +} From 3e7be19b6fce62e7e720863153f5b2162236f4e7 Mon Sep 17 00:00:00 2001 From: Graham Christensen Date: Tue, 24 Sep 2024 12:03:49 -0400 Subject: [PATCH 04/10] derp, extra eol at the end --- src/github_actions.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/github_actions.rs b/src/github_actions.rs index 040c344..2025e57 100644 --- a/src/github_actions.rs +++ b/src/github_actions.rs @@ -49,5 +49,5 @@ fn escape_key_value<'a>(key: &'a str, value: &'a str) -> Result { return Err(Error::ValueContainsDelimiter); } - Ok(format!("{key}<<{delimiter}{eol}{value}{eol}{delimiter}")) + Ok(format!("{key}<<{delimiter}{eol}{value}{eol}{delimiter}{eol}")) } From e0b268807af73d9e85608b72fe29887d068c7ede Mon Sep 17 00:00:00 2001 From: Graham Christensen Date: Tue, 24 Sep 2024 12:05:31 -0400 Subject: [PATCH 05/10] fmt --- src/github_actions.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/github_actions.rs b/src/github_actions.rs index 2025e57..192d4ac 100644 --- a/src/github_actions.rs +++ b/src/github_actions.rs @@ -49,5 +49,7 @@ fn escape_key_value<'a>(key: &'a str, value: &'a str) -> Result { return Err(Error::ValueContainsDelimiter); } - Ok(format!("{key}<<{delimiter}{eol}{value}{eol}{delimiter}{eol}")) + Ok(format!( + "{key}<<{delimiter}{eol}{value}{eol}{delimiter}{eol}" + )) } From 53b28e3835618317f384ca4406c133fb388b6023 Mon Sep 17 00:00:00 2001 From: Graham Christensen Date: Tue, 24 Sep 2024 12:36:34 -0400 Subject: [PATCH 06/10] Fixup readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 110edd8..823d771 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ This action sets outputs for integrating into CD pipelines: - `flake_name` Name of the flake. Example: `DeterminateSystems/flakehub-push` - `flake_version` Name of the flake. Example: `0.1.99+rev-2075013a3f3544d45a96f4b35df4ed03cd53779c` - `flakeref_descriptive` A loose reference to this release. Depending on this reference will require at least this version, and will also resolve to newer releases. This output is not sufficient for deployment pipelines, use `flake_exact` instead. Example: `DeterminateSystems/flakehub-push/0.1.99+rev-2075013a3f3544d45a96f4b35df4ed03cd53779c` -- `flake_exact` A precise reference that always resolves to this to this exact release. Example: `DeterminateSystems/flakehub-push/=0.1.99+rev-2075013a3f3544d45a96f4b35df4ed03cd53779c` +- `flakeref_exact` A precise reference that always resolves to this to this exact release. Example: `DeterminateSystems/flakehub-push/=0.1.99+rev-2075013a3f3544d45a96f4b35df4ed03cd53779c` ## More Information From 8a2eb3450e068c63decc3b9a2fe35dbd954f6152 Mon Sep 17 00:00:00 2001 From: Graham Christensen Date: Tue, 24 Sep 2024 12:36:45 -0400 Subject: [PATCH 07/10] Set outputs if this ref has been published before --- src/main.rs | 51 +++++++++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/src/main.rs b/src/main.rs index 5185dd2..3b1111a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -140,6 +140,9 @@ async fn execute() -> Result { upload_name = ctx.upload_name, release_version = &ctx.release_version, ); + + set_release_outputs(&ctx.upload_name, &ctx.release_version).await; + if ctx.error_if_release_conflicts { return Err(Error::Conflict { upload_name: ctx.upload_name.to_string(), @@ -182,28 +185,7 @@ async fn execute() -> Result { ctx.release_version ); - let outputs = [ - ("flake_name", &ctx.upload_name), - ("flake_version", &ctx.release_version), - ( - "flakeref_descriptive", - &format!("{}/{}", ctx.upload_name, ctx.release_version), - ), - ( - "flakeref_exact", - &format!("{}/={}", ctx.upload_name, ctx.release_version), - ), - ]; - for (output_name, value) in outputs.into_iter() { - if let Err(e) = github_actions::set_output(output_name, value).await { - tracing::warn!( - "Failed to set the `{}` output to {}: {}", - output_name, - value, - e - ); - } - } + set_release_outputs(&ctx.upload_name, &ctx.release_version).await; Ok(ExitCode::SUCCESS) } @@ -236,3 +218,28 @@ impl Display for Visibility { } } } + +async fn set_release_outputs(upload_name: &str, release_version: &str) { + let outputs = [ + ("flake_name", upload_name), + ("flake_version", release_version), + ( + "flakeref_descriptive", + &format!("{}/{}", upload_name, release_version), + ), + ( + "flakeref_exact", + &format!("{}/={}", upload_name, release_version), + ), + ]; + for (output_name, value) in outputs.into_iter() { + if let Err(e) = github_actions::set_output(output_name, value).await { + tracing::warn!( + "Failed to set the `{}` output to {}: {}", + output_name, + value, + e + ); + } + } +} From 080004135fb796c5a60ea89365b6b40fc533dc0d Mon Sep 17 00:00:00 2001 From: Graham Christensen Date: Tue, 24 Sep 2024 13:03:11 -0400 Subject: [PATCH 08/10] Don't truncate --- src/github_actions.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/github_actions.rs b/src/github_actions.rs index 192d4ac..08ac9b4 100644 --- a/src/github_actions.rs +++ b/src/github_actions.rs @@ -21,7 +21,6 @@ pub(crate) enum Error { pub(crate) async fn set_output<'a>(name: &'a str, value: &'a str) -> Result<(), Error> { let output_path = std::env::var_os("GITHUB_OUTPUT").ok_or(Error::GithubOutputUnset)?; let mut fh = tokio::fs::OpenOptions::new() - .create(true) .read(true) .write(true) .truncate(false) From 73499d550033382c2cdfe95544a03c04ea4e5d86 Mon Sep 17 00:00:00 2001 From: Graham Christensen Date: Tue, 24 Sep 2024 13:05:03 -0400 Subject: [PATCH 09/10] ...don't create --- src/github_actions.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/github_actions.rs b/src/github_actions.rs index 08ac9b4..906e82f 100644 --- a/src/github_actions.rs +++ b/src/github_actions.rs @@ -21,8 +21,8 @@ pub(crate) enum Error { pub(crate) async fn set_output<'a>(name: &'a str, value: &'a str) -> Result<(), Error> { let output_path = std::env::var_os("GITHUB_OUTPUT").ok_or(Error::GithubOutputUnset)?; let mut fh = tokio::fs::OpenOptions::new() - .read(true) .write(true) + .append(true) .truncate(false) .open(&output_path) .await From 9c740185853f48a1dcc73fb1351fcc6ad405d90f Mon Sep 17 00:00:00 2001 From: Graham Christensen Date: Tue, 24 Sep 2024 14:25:12 -0400 Subject: [PATCH 10/10] Address feedback --- README.md | 14 ++++++++------ src/main.rs | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 823d771..9bc2b5d 100644 --- a/README.md +++ b/README.md @@ -16,12 +16,14 @@ Although the `flakehub-push` Action requires little configuration, you may benef ## Integration -This action sets outputs for integrating into CD pipelines: - -- `flake_name` Name of the flake. Example: `DeterminateSystems/flakehub-push` -- `flake_version` Name of the flake. Example: `0.1.99+rev-2075013a3f3544d45a96f4b35df4ed03cd53779c` -- `flakeref_descriptive` A loose reference to this release. Depending on this reference will require at least this version, and will also resolve to newer releases. This output is not sufficient for deployment pipelines, use `flake_exact` instead. Example: `DeterminateSystems/flakehub-push/0.1.99+rev-2075013a3f3544d45a96f4b35df4ed03cd53779c` -- `flakeref_exact` A precise reference that always resolves to this to this exact release. Example: `DeterminateSystems/flakehub-push/=0.1.99+rev-2075013a3f3544d45a96f4b35df4ed03cd53779c` +This action sets outputs for integrating into continuous delivery pipelines: + +| Output | Description | Example | +| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------- | +| `flake_name` | Name of the flake. | `DeterminateSystems/flakehub-push` | +| `flake_version` | Version of the published flake. | `0.1.99+rev-2075013a3f3544d45a96f4b35df4ed03cd53779c` | +| `flakeref_exact` | A precise reference that always resolves to this to this exact release. | `DeterminateSystems/flakehub-push/=0.1.99+rev-2075013a3f3544d45a96f4b35df4ed03cd53779c` | +| `flakeref_at_least` | A loose reference to this release. Depending on this reference will require at least this version, and will also resolve to newer releases. This output is not sufficient for deployment pipelines, use `flake_exact` instead. | `DeterminateSystems/flakehub-push/0.1.99+rev-2075013a3f3544d45a96f4b35df4ed03cd53779c` | ## More Information diff --git a/src/main.rs b/src/main.rs index 3b1111a..6bc8c1c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -224,7 +224,7 @@ async fn set_release_outputs(upload_name: &str, release_version: &str) { ("flake_name", upload_name), ("flake_version", release_version), ( - "flakeref_descriptive", + "flakeref_at_least", &format!("{}/{}", upload_name, release_version), ), (