Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 171 additions & 0 deletions .github/workflows/wab-marketplace-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
name: WAB → AWS Marketplace

# Publishes infra/wab to the AWS Marketplace listing (ContainerProduct prod-67ziqtkrihz34).
#
# VERSION SOURCE OF TRUTH: infra/wab/package.json `version`. The published Marketplace version
# name is ALWAYS derived from package.json — the `infra/v*` git tag is ONLY the trigger (it is
# date-based, e.g. infra/v2026-June-26, and is never parsed for a version). These two MUST stay
# decoupled. `version_override` is a manual escape hatch (e.g. the one-time 1.0.8 -> 1.4.7
# catch-up), not the normal path.
#
# Naming mirrors the existing listing exactly:
# package.json 1.4.7
# ECR image tag bsv-blockchain/wab:1.4.7 (bare, like the existing wab:1.0.7)
# Marketplace VersionTitle "v1.4.7" (v-prefixed, like the existing v1.0.7 / v1.0.8)
#
# IMPORTANT: this file MUST live in the repo ROOT .github/workflows/. GitHub never runs workflow
# files placed in subdirectories such as infra/wab/.github/workflows/ — that is exactly why the old
# build-and-push.yml stopped firing when WAB moved into the monorepo.

on:
push:
tags:
- 'infra/v*' # same trigger as infra-release.yaml — the tag is only the trigger
workflow_dispatch:
inputs:
version_override:
description: 'Manual escape hatch: publish this version instead of reading package.json'
required: false
default: ''

concurrency:
group: wab-marketplace-release
cancel-in-progress: false # never cancel a half-registered Catalog change set

env:
AWS_REGION: us-east-1
MP_ECR_ACCOUNT: '709825985650' # AWS Marketplace-managed ECR account
MP_ECR_REPO: bsv-blockchain/wab # existing Marketplace repo for this product
PRODUCT_ID: prod-67ziqtkrihz34 # WAB ContainerProduct
WAB_DIR: infra/wab

jobs:
publish:
name: Publish WAB to Marketplace
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write # OIDC: assume the seller-account publisher role (no static keys)
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6

- name: Resolve version from package.json
id: ver
run: |
# The version name is ALWAYS package.json; the git tag is only the trigger (keep decoupled).
if [ -n "${{ github.event.inputs.version_override }}" ]; then
VERSION="${{ github.event.inputs.version_override }}"
else
VERSION="$(node -p "require('./${WAB_DIR}/package.json').version")"
fi
[ -n "$VERSION" ] || { echo "No version found"; exit 1; }
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "title=v$VERSION" >> "$GITHUB_OUTPUT"
echo "Resolved WAB version: $VERSION (Marketplace title: v$VERSION)"

- name: Configure AWS credentials (OIDC)
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6.2.0
with:
role-to-assume: ${{ vars.WAB_MP_ROLE_ARN }}
aws-region: ${{ env.AWS_REGION }}

- name: Skip if this version is already published
id: exists
run: |
TITLE="${{ steps.ver.outputs.title }}"
# Use DetailsDocument (clean JSON). The legacy `Details` field returns non-strict JSON
# (raw newlines in release notes) which breaks `jq fromjson` and would make this check
# silently match nothing.
TITLES="$(aws marketplace-catalog describe-entity \
--catalog AWSMarketplace \
--entity-id "${PRODUCT_ID}" \
--query DetailsDocument --output json 2>/dev/null \
| jq -r '.Versions[]?.VersionTitle' 2>/dev/null || true)"
if echo "$TITLES" | grep -qx "$TITLE"; then
echo "already=true" >> "$GITHUB_OUTPUT"
echo "Version $TITLE already exists on the listing — nothing to do."
else
echo "already=false" >> "$GITHUB_OUTPUT"
echo "Version $TITLE not present — will build, push, and register."
fi

- name: Log in to AWS Marketplace ECR
if: steps.exists.outputs.already == 'false'
run: |
aws ecr get-login-password --region "${AWS_REGION}" \
| docker login --username AWS --password-stdin \
"${MP_ECR_ACCOUNT}.dkr.ecr.${AWS_REGION}.amazonaws.com"

- name: Build and push image to Marketplace ECR
if: steps.exists.outputs.already == 'false'
run: |
VERSION="${{ steps.ver.outputs.version }}"
IMAGE="${MP_ECR_ACCOUNT}.dkr.ecr.${AWS_REGION}.amazonaws.com/${MP_ECR_REPO}:${VERSION}"
# context = infra/wab (self-contained Dockerfile; same recipe infra-release.yaml uses).
docker build --platform linux/amd64 -t "$IMAGE" "${WAB_DIR}"
docker push "$IMAGE"
echo "Pushed $IMAGE"

- name: Register new version on the listing (AddDeliveryOptions)
if: steps.exists.outputs.already == 'false'
id: changeset
run: |
VERSION="${{ steps.ver.outputs.version }}"
TITLE="${{ steps.ver.outputs.title }}"
IMAGE="${MP_ECR_ACCOUNT}.dkr.ecr.${AWS_REGION}.amazonaws.com/${MP_ECR_REPO}:${VERSION}"

# DeliveryOptionTitle and CompatibleServices match the live listing (verified via
# describe-entity). The Catalog API expects the "Anywhere" services as hyphenated
# tokens: ECS-Anywhere / EKS-Anywhere. Uses DetailsDocument (not legacy Details).
CHANGE_SET=$(jq -nc --arg id "$PRODUCT_ID" --arg t "$TITLE" --arg img "$IMAGE" '
[{
ChangeType: "AddDeliveryOptions",
Entity: { Identifier: $id, Type: "ContainerProduct@1.0" },
DetailsDocument: {
Version: {
VersionTitle: $t,
ReleaseNotes: ("WAB \($t). See https://github.com/bsv-blockchain/ts-stack/tree/main/infra/wab")
},
DeliveryOptions: [{
DeliveryOptionTitle: "WAB Container - ECS/EKS Deployment",
Details: {
EcrDeliveryOptionDetails: {
ContainerImages: [ $img ],
CompatibleServices: [ "ECS", "EKS", "ECS-Anywhere", "EKS-Anywhere" ],
Description: "Wallet Authentication Backend",
UsageInstructions: "See https://github.com/bsv-blockchain/ts-stack/tree/main/infra/wab"
}
}
}]
}
}]')

CS_ID=$(aws marketplace-catalog start-change-set \
--catalog AWSMarketplace \
--change-set "$CHANGE_SET" \
--query 'ChangeSetId' --output text)
echo "change_set_id=$CS_ID" >> "$GITHUB_OUTPUT"
echo "Started change set $CS_ID for $TITLE"

- name: Wait for change set to settle (scan can take minutes–hours)
if: steps.exists.outputs.already == 'false'
run: |
CS_ID="${{ steps.changeset.outputs.change_set_id }}"
for i in $(seq 1 60); do
STATUS=$(aws marketplace-catalog describe-change-set \
--catalog AWSMarketplace --change-set-id "$CS_ID" \
--query 'Status' --output text)
echo "[$i] status=$STATUS"
case "$STATUS" in
SUCCEEDED) echo "Version published."; exit 0 ;;
FAILED|CANCELLED)
echo "Change set $STATUS. Error details:"
aws marketplace-catalog describe-change-set --catalog AWSMarketplace \
--change-set-id "$CS_ID" --query 'ChangeSet[].ErrorDetailList'
exit 1 ;;
esac
sleep 60
done
echo "Still PREPARING/APPLYING after timeout; check the Requests log in the portal."
echo "Change set: $CS_ID"
20 changes: 20 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# ts-stack — repo guidance

## Releasing infra/wab to AWS Marketplace

The Marketplace version is driven by `infra/wab/package.json` `version` — the same source of
truth `infra-release.yaml` uses for GHCR. To release: bump that version, then push an `infra/v*` tag.

- Workflow: `.github/workflows/wab-marketplace-release.yml` (must be at repo root — GitHub does not
run workflows under `infra/wab/.github/workflows/`).
- The published version name is **always** derived from `infra/wab/package.json`; the `infra/v*` git
tag (date-based) is **only the trigger** and is never parsed for a version. Marketplace version
titles are `v`-prefixed (`v1.4.7`) to match the existing listing; the ECR image tag is bare
(`wab:1.4.7`).
- Marketplace product ID: `prod-67ziqtkrihz34` (ContainerProduct@1.0).
- Image goes to the Marketplace ECR `709825985650.dkr.ecr.us-east-1.amazonaws.com/bsv-blockchain/wab:<version>`,
NOT GHCR or Docker Hub.
- Publishing = push image to Marketplace ECR THEN register the version via Catalog API
`StartChangeSet` / `AddDeliveryOptions`. Pushing the image alone does nothing buyers can see.
- Version names on the listing are immutable and must be unique; never reuse one.
- New versions are scanned (minutes–hours) before going live.
51 changes: 0 additions & 51 deletions infra/wab/.github/workflows/build-and-push.yml

This file was deleted.

66 changes: 0 additions & 66 deletions infra/wab/.github/workflows/image.yaml

This file was deleted.