name: Build & Publish Release env: NIX_CONFIG: experimental-features = nix-command flakes on: workflow_dispatch: inputs: release_type: description: "Release type: 'dev' or 'stable'" required: true default: "dev" type: choice options: - dev - stable description: description: "Release description" required: true type: string jobs: build: name: Build & Publish Release runs-on: host steps: - name: Set up repository uses: actions/checkout@v4 with: submodules: recursive - name: Login to Docker Hub env: DOCKER_USER: ${{ secrets.DOCKER_USER }} DOCKER_PASSWD: ${{ secrets.DOCKER_PASSWD }} run: | set -eu DOCKER_USER="$(printf '%s' "$DOCKER_USER" | tr -d '\r\n')" DOCKER_PASSWD="$(printf '%s' "$DOCKER_PASSWD" | tr -d '\r\n')" printf '%s' "$DOCKER_PASSWD" | nix-shell -p docker --run "docker login docker.io --username \"$DOCKER_USER\" --password-stdin" - name: Build & Push Docker image run: | nix-shell -p docker --run "docker build -f dockerfile -t tensamin/iota:latest . && docker push tensamin/iota:latest" - name: Read release metadata id: version env: RELEASE_TYPE: ${{ inputs.release_type }} run: | set -eu VERSION="$(nix eval --raw .#default.version)" SHORT_SHA="$(git rev-parse --short=7 HEAD)" case "$RELEASE_TYPE" in dev) TAG="${VERSION}-dev-${SHORT_SHA}" PRERELEASE="true" ;; stable) TAG="$VERSION" PRERELEASE="false" ;; *) echo "release_type must be either 'dev' or 'stable'" exit 1 ;; esac echo "version=$VERSION" >> "$FORGEJO_OUTPUT" echo "tag=$TAG" >> "$FORGEJO_OUTPUT" echo "title=$TAG" >> "$FORGEJO_OUTPUT" echo "prerelease=$PRERELEASE" >> "$FORGEJO_OUTPUT" ARCH="$(uname -m)" echo "arch=$ARCH" >> "$FORGEJO_OUTPUT" echo "asset_name=iota-${TAG}-linux-${ARCH}.zip" >> "$FORGEJO_OUTPUT" echo "update_manifest_name=iota-update-${TAG}-linux-${ARCH}.json" >> "$FORGEJO_OUTPUT" echo "channel_tag=iota-updates-${RELEASE_TYPE}-linux-${ARCH}" >> "$FORGEJO_OUTPUT" echo "channel_manifest_name=iota-update-linux-${ARCH}.json" >> "$FORGEJO_OUTPUT" - name: Build and validate installer bundle env: TAG: ${{ steps.version.outputs.tag }} ASSET_NAME: ${{ steps.version.outputs.asset_name }} ARCH: ${{ steps.version.outputs.arch }} UPDATE_MANIFEST_NAME: ${{ steps.version.outputs.update_manifest_name }} CHANNEL_TAG: ${{ steps.version.outputs.channel_tag }} CHANNEL_MANIFEST_NAME: ${{ steps.version.outputs.channel_manifest_name }} RELEASE_TYPE: ${{ inputs.release_type }} SERVER_URL: ${{ forgejo.server_url }} REPO: ${{ forgejo.repository }} IOTA_RELEASE_SIGNING_KEY: ${{ secrets.IOTA_RELEASE_SIGNING_KEY }} run: | set -eu : "${IOTA_RELEASE_SIGNING_KEY:?IOTA_RELEASE_SIGNING_KEY secret is required}" nix build "git+file://$PWD?submodules=1#default" --print-build-logs mkdir -p dist/bin install -m755 result/bin/iota dist/bin/iota install -m755 result/bin/iota-daemon dist/bin/iota-daemon install -m755 result/bin/iota-updater dist/bin/iota-updater UPDATE_BASE_URL="${SERVER_URL%/}/${REPO}/releases/download/${TAG}" UPDATE_CHANNEL_BASE_URL="${SERVER_URL%/}/${REPO}/releases/download/${CHANNEL_TAG}" PUBLISHED_AT="$(date -u +%Y-%m-%dT%H:%M:%SZ)" export ARCH PUBLISHED_AT RELEASE_TYPE TAG UPDATE_BASE_URL UPDATE_MANIFEST_NAME nix-shell -p coreutils jq --run 'bash scripts/build-update-manifest.sh dist/bin "$TAG" "$RELEASE_TYPE" "$PUBLISHED_AT" linux "$ARCH" "$UPDATE_BASE_URL" "dist/$UPDATE_MANIFEST_NAME"' UPDATE_PUBLIC_KEY="$(result/bin/iota-release sign "dist/$UPDATE_MANIFEST_NAME" "dist/$UPDATE_MANIFEST_NAME.sig")" bash scripts/build-release-bundle.sh \ dist/bin \ "$TAG" \ "$UPDATE_CHANNEL_BASE_URL/$CHANNEL_MANIFEST_NAME" \ "$UPDATE_PUBLIC_KEY" \ "$UPDATE_CHANNEL_BASE_URL/$CHANNEL_MANIFEST_NAME.sig" \ "dist/$ASSET_NAME" result/bin/iota-bundle "dist/$ASSET_NAME" - name: Create release and upload release assets env: TOKEN: ${{ forgejo.token }} API: ${{ forgejo.api_url }} REPO: ${{ forgejo.repository }} SHA: ${{ forgejo.sha }} TAG: ${{ steps.version.outputs.tag }} TITLE: ${{ steps.version.outputs.title }} PRERELEASE: ${{ steps.version.outputs.prerelease }} ASSET_NAME: ${{ steps.version.outputs.asset_name }} UPDATE_MANIFEST_NAME: ${{ steps.version.outputs.update_manifest_name }} CHANNEL_TAG: ${{ steps.version.outputs.channel_tag }} CHANNEL_MANIFEST_NAME: ${{ steps.version.outputs.channel_manifest_name }} RELEASE_TYPE: ${{ inputs.release_type }} DESCRIPTION: ${{ inputs.description }} run: | nix-shell -p curl jq --run ' set -eu HTTP_STATUS=$(curl -s -w "%{http_code}" -o release_out.json \ -H "Authorization: token $TOKEN" \ "$API/repos/$REPO/releases/tags/$TAG") if [ "$HTTP_STATUS" = "200" ]; then echo "Release $TAG already exists." RELEASE_ID="$(jq -r .id release_out.json)" else echo "Creating release for $TAG" RELEASE_JSON="$(curl -f -sS -X POST "$API/repos/$REPO/releases" \ -H "Authorization: token $TOKEN" \ -H "Content-Type: application/json" \ -d "$(jq -n \ --arg tag "$TAG" \ --arg name "$TITLE" \ --arg body "$DESCRIPTION" \ --arg target "$SHA" \ --argjson prerelease "$PRERELEASE" \ '"'"'{ tag_name: $tag, name: $name, body: $body, target_commitish: $target, draft: false, prerelease: $prerelease }'"'"')")" RELEASE_ID="$(echo "$RELEASE_JSON" | jq -r .id)" fi upload_asset() { TARGET_RELEASE_ID="$1" ASSET="$2" PATHNAME="$3" curl -fsS -X POST "$API/repos/$REPO/releases/$TARGET_RELEASE_ID/assets?name=$ASSET" \ -H "Authorization: token $TOKEN" \ -F "attachment=@$PATHNAME" } upload_asset "$RELEASE_ID" iota dist/bin/iota upload_asset "$RELEASE_ID" iota-daemon dist/bin/iota-daemon upload_asset "$RELEASE_ID" iota-updater dist/bin/iota-updater upload_asset "$RELEASE_ID" "$UPDATE_MANIFEST_NAME.sig" "dist/$UPDATE_MANIFEST_NAME.sig" upload_asset "$RELEASE_ID" "$ASSET_NAME" "dist/$ASSET_NAME" upload_asset "$RELEASE_ID" "$UPDATE_MANIFEST_NAME" "dist/$UPDATE_MANIFEST_NAME" CHANNEL_STATUS=$(curl -s -w "%{http_code}" -o channel_out.json \ -H "Authorization: token $TOKEN" \ "$API/repos/$REPO/releases/tags/$CHANNEL_TAG") if [ "$CHANNEL_STATUS" = "200" ]; then CHANNEL_RELEASE_ID="$(jq -r .id channel_out.json)" else CHANNEL_JSON="$(curl -f -sS -X POST "$API/repos/$REPO/releases" \ -H "Authorization: token $TOKEN" \ -H "Content-Type: application/json" \ -d "$(jq -n \ --arg tag "$CHANNEL_TAG" \ --arg name "Iota $RELEASE_TYPE update channel" \ --arg target "$SHA" \ '"'"'{ tag_name: $tag, name: $name, body: "Managed by the release workflow.", target_commitish: $target, draft: false, prerelease: true }'"'"')")" CHANNEL_RELEASE_ID="$(echo "$CHANNEL_JSON" | jq -r .id)" fi CHANNEL_ASSETS="$(curl -fsS \ -H "Authorization: token $TOKEN" \ "$API/repos/$REPO/releases/$CHANNEL_RELEASE_ID/assets")" for CHANNEL_ASSET in "$CHANNEL_MANIFEST_NAME" "$CHANNEL_MANIFEST_NAME.sig"; do echo "$CHANNEL_ASSETS" | jq -r --arg name "$CHANNEL_ASSET" '"'"'.[] | select(.name == $name) | .id'"'"' | while read -r ASSET_ID; do [ -n "$ASSET_ID" ] || continue curl -fsS -X DELETE "$API/repos/$REPO/releases/assets/$ASSET_ID" \ -H "Authorization: token $TOKEN" done done upload_asset "$CHANNEL_RELEASE_ID" "$CHANNEL_MANIFEST_NAME.sig" "dist/$UPDATE_MANIFEST_NAME.sig" upload_asset "$CHANNEL_RELEASE_ID" "$CHANNEL_MANIFEST_NAME" "dist/$UPDATE_MANIFEST_NAME" '