From b4180f20148d1d1ac3040bd6601475a388d96234 Mon Sep 17 00:00:00 2001 From: Christopher Haar Date: Thu, 16 Jul 2026 21:25:06 +0200 Subject: [PATCH] feature/marketplace-extension Signed-off-by: Christopher Haar --- .github/workflows/ci.yml | 12 ++++++++++++ extensions/icons/icon.svg | 18 ++++++++++++++++++ flake.nix | 2 +- nix/apps.nix | 39 +++++++++++++++++++++++++++++++++++---- nix/functions.nix | 5 ++++- 5 files changed, 70 insertions(+), 6 deletions(-) create mode 100644 extensions/icons/icon.svg diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e3f8be6eb..f61341231 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -95,6 +95,18 @@ jobs: username: ${{ secrets.UP_ROBOT_ID }} password: ${{ secrets.UP_ROBOT_TOKEN }} + # On a release run, fetch the GitHub release's notes so the push app + # embeds them in the package's Marketplace extensions. Ordinary runs + # skip this; the push app only appends the notes when the file exists. + - name: Generate release notes + if: inputs.tag != '' + env: + GH_TOKEN: ${{ github.token }} + TAG: ${{ inputs.tag }} + run: | + gh release view "${TAG}" --json body -q .body > release_notes.md || true + [ -s release_notes.md ] || rm -f release_notes.md + # With a tag input (a release) push that exact version; otherwise push a # dev version the push app derives from git metadata. - name: Build and Push diff --git a/extensions/icons/icon.svg b/extensions/icons/icon.svg new file mode 100644 index 000000000..c83b0bf2b --- /dev/null +++ b/extensions/icons/icon.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/flake.nix b/flake.nix index 327b4f3da..0a167c2aa 100644 --- a/flake.nix +++ b/flake.nix @@ -167,7 +167,7 @@ }; push = apps.push { inherit crossplane version; - dockerCredentialUp = pkgs.upbound; + inherit (pkgs) upbound; }; run = apps.run { inherit crossplane functionsPkg; diff --git a/nix/apps.nix b/nix/apps.nix index 4073ed6cf..c7f6fab74 100644 --- a/nix/apps.nix +++ b/nix/apps.nix @@ -152,12 +152,18 @@ ); }; - # Push the Crossplane project to a registry. Uses a dev version tag unless - # --tag is passed, e.g.: nix run .#push -- --tag v0.1.0 + # Push the Crossplane project to a registry, then append the package's + # Upbound Marketplace extensions to the pushed image. Uses a dev version tag + # unless --tag is passed, e.g.: nix run .#push -- --tag v0.1.0 + # + # The Marketplace renders package assets from a well-known extensions image + # layout: icons/ (committed under extensions/), readme/readme.md (copied + # from README.md), and release-notes/ (included when a release_notes.md + # exists in the working directory - CI writes it on release runs). push = { crossplane, - dockerCredentialUp, + upbound, version, }: { @@ -166,9 +172,14 @@ program = pkgs.lib.getExe ( pkgs.writeShellApplication { name = "modelplane-push"; + # upbound provides both docker-credential-up, which the Crossplane + # CLI uses to authenticate the push, and up, which appends the + # extensions. runtimeInputs = [ crossplane - dockerCredentialUp + upbound + pkgs.coreutils + pkgs.yq-go ]; inheritPath = false; text = '' @@ -177,6 +188,26 @@ set -- --tag "${version}" "$@" fi crossplane project push "$@" + + tag="" + while [ $# -gt 1 ]; do + if [ "$1" = "--tag" ]; then tag="$2"; fi + shift + done + repository=$(yq '.spec.repository' crossplane-project.yaml) + + extensions=$(mktemp -d) + trap 'rm -rf "$extensions"' EXIT + cp -R extensions/. "$extensions/" + mkdir -p "$extensions/readme" + cp README.md "$extensions/readme/readme.md" + if [ -f release_notes.md ]; then + mkdir -p "$extensions/release-notes" + cp release_notes.md "$extensions/release-notes/" + fi + + echo "Appending Marketplace extensions to $repository:$tag" + up alpha xpkg append "$repository:$tag" --extensions-root "$extensions" ''; } ); diff --git a/nix/functions.nix b/nix/functions.nix index 473d4f2cb..38ec32d45 100644 --- a/nix/functions.nix +++ b/nix/functions.nix @@ -77,7 +77,10 @@ let let targetSystem = archToNixSystem.${arch}; targetPkgs = - if targetSystem == pkgs.system then pkgs else import pkgs.path { system = targetSystem; }; + if targetSystem == pkgs.stdenv.hostPlatform.system then + pkgs + else + import pkgs.path { system = targetSystem; }; in { inherit targetPkgs;