Fix release workflow to complete successfully end-to-end

Related to systematic release workflow failures. The workflow has never
successfully completed from start to finish since validation was added.

Root causes identified and fixed:

1. **GraphQL node_id vs numeric release ID**: The create-release job was
   using `gh release view --json id` which returns a GraphQL node_id
   (RE_kwDON5nJtM4PmlTt) instead of the numeric database ID (261772525)
   needed by the REST API. The validation workflow then failed with 404
   when trying to download assets. Fixed by using `gh api` to get the
   numeric ID from the releases list endpoint.

2. **Missing binaries in Docker image**: The validation script expects 26
   binaries + 3 Windows symlinks in /opt/pulse/bin/, but the Dockerfile
   was only copying a subset. Missing binaries included the main pulse
   server binary, armv6/386 builds for all agents, and caused immediate
   validation failure. Fixed by copying all built binaries from
   backend-builder stage.

3. **Assets-only validation fallback broken**: When Docker image pull
   times out, the workflow falls back to assets-only validation but was
   still calling the validation script without --skip-docker flag,
   causing it to fail on the first docker command. Fixed by passing
   --skip-docker flag in the fallback path.

4. **Asset download pagination**: The asset download was not using
   --paginate, which would cause silent failures once we exceed 30 assets
   (currently at 27). Fixed by adding --paginate to gh api call.

All fixes verified locally and address the complete failure chain.
This commit is contained in:
rcourtman
2025-11-12 14:59:16 +00:00
parent 441eec8b0f
commit a136a0d255
3 changed files with 27 additions and 8 deletions

View File

@@ -373,8 +373,15 @@ jobs:
rm -f "$NOTES_FILE"
echo "release_url=$(gh release view ${TAG} --json url -q .url)" >> $GITHUB_OUTPUT
echo "release_id=$(gh release view ${TAG} --json id -q .id)" >> $GITHUB_OUTPUT
# Get the numeric release ID from the REST API (not GraphQL node_id)
# The validation workflow needs the numeric ID for REST API calls
# Note: /releases/tags/{tag} endpoint doesn't work for draft releases,
# so we list all releases and filter by tag_name
RELEASE_JSON=$(gh api "repos/${{ github.repository }}/releases" | jq ".[] | select(.tag_name == \"${TAG}\")")
RELEASE_ID=$(echo "$RELEASE_JSON" | jq -r '.id')
echo "release_url=$(echo "$RELEASE_JSON" | jq -r '.html_url')" >> $GITHUB_OUTPUT
echo "release_id=${RELEASE_ID}" >> $GITHUB_OUTPUT
echo "tag=${TAG}" >> $GITHUB_OUTPUT
- name: Upload checksums.txt

View File

@@ -124,7 +124,8 @@ jobs:
cd release
# Get asset info (id and name) - API works with GITHUB_TOKEN for draft releases
ASSETS_JSON=$(gh api "repos/${{ github.repository }}/releases/${{ steps.context.outputs.release_id }}/assets")
# Use --paginate to handle releases with >30 assets
ASSETS_JSON=$(gh api --paginate "repos/${{ github.repository }}/releases/${{ steps.context.outputs.release_id }}/assets")
if [ "$(echo "$ASSETS_JSON" | jq '. | length')" -eq 0 ]; then
echo "::error::No assets found in release"
@@ -222,8 +223,8 @@ jobs:
echo "Running assets-only validation (Docker image not available)..."
scripts/validate-release.sh \
"${{ steps.context.outputs.version }}" \
"rcourtman/pulse:${{ steps.context.outputs.tag }}" \
"release" 2>&1 | tee "$OUTPUT_FILE" || true
--skip-docker \
"release" 2>&1 | tee "$OUTPUT_FILE"
fi
VALIDATION_EXIT_CODE=$?

View File

@@ -226,17 +226,26 @@ COPY scripts/install-sensor-proxy.sh /opt/pulse/scripts/install-sensor-proxy.sh
COPY scripts/install-docker.sh /opt/pulse/scripts/install-docker.sh
RUN chmod 755 /opt/pulse/scripts/install-docker-agent.sh /opt/pulse/scripts/install-container-agent.sh /opt/pulse/scripts/install-host-agent.sh /opt/pulse/scripts/install-host-agent.ps1 /opt/pulse/scripts/uninstall-host-agent.sh /opt/pulse/scripts/uninstall-host-agent.ps1 /opt/pulse/scripts/install-sensor-proxy.sh /opt/pulse/scripts/install-docker.sh
# Copy multi-arch docker-agent binaries for download endpoint
# Copy all binaries for download endpoint
RUN mkdir -p /opt/pulse/bin
# Main pulse server binary (for validation)
COPY --from=backend-builder /app/pulse /opt/pulse/bin/pulse
# Docker agent binaries (all architectures)
COPY --from=backend-builder /app/pulse-docker-agent-linux-amd64 /opt/pulse/bin/
COPY --from=backend-builder /app/pulse-docker-agent-linux-arm64 /opt/pulse/bin/
COPY --from=backend-builder /app/pulse-docker-agent-linux-armv7 /opt/pulse/bin/
COPY --from=backend-builder /app/pulse-docker-agent-linux-armv6 /opt/pulse/bin/
COPY --from=backend-builder /app/pulse-docker-agent-linux-386 /opt/pulse/bin/
COPY --from=backend-builder /app/pulse-docker-agent /opt/pulse/bin/pulse-docker-agent
# Copy multi-arch host-agent binaries for download endpoint
# Host agent binaries (all platforms and architectures)
COPY --from=backend-builder /app/pulse-host-agent-linux-amd64 /opt/pulse/bin/
COPY --from=backend-builder /app/pulse-host-agent-linux-arm64 /opt/pulse/bin/
COPY --from=backend-builder /app/pulse-host-agent-linux-armv7 /opt/pulse/bin/
COPY --from=backend-builder /app/pulse-host-agent-linux-armv6 /opt/pulse/bin/
COPY --from=backend-builder /app/pulse-host-agent-linux-386 /opt/pulse/bin/
COPY --from=backend-builder /app/pulse-host-agent-darwin-amd64 /opt/pulse/bin/
COPY --from=backend-builder /app/pulse-host-agent-darwin-arm64 /opt/pulse/bin/
COPY --from=backend-builder /app/pulse-host-agent-windows-amd64.exe /opt/pulse/bin/
@@ -247,10 +256,12 @@ RUN ln -s pulse-host-agent-windows-amd64.exe /opt/pulse/bin/pulse-host-agent-win
ln -s pulse-host-agent-windows-arm64.exe /opt/pulse/bin/pulse-host-agent-windows-arm64 && \
ln -s pulse-host-agent-windows-386.exe /opt/pulse/bin/pulse-host-agent-windows-386
# Copy multi-arch pulse-sensor-proxy binaries for download endpoint
# Sensor proxy binaries (all Linux architectures)
COPY --from=backend-builder /app/pulse-sensor-proxy-linux-amd64 /opt/pulse/bin/
COPY --from=backend-builder /app/pulse-sensor-proxy-linux-arm64 /opt/pulse/bin/
COPY --from=backend-builder /app/pulse-sensor-proxy-linux-armv7 /opt/pulse/bin/
COPY --from=backend-builder /app/pulse-sensor-proxy-linux-armv6 /opt/pulse/bin/
COPY --from=backend-builder /app/pulse-sensor-proxy-linux-386 /opt/pulse/bin/
COPY --from=backend-builder /app/pulse-sensor-proxy /opt/pulse/bin/pulse-sensor-proxy
# Create config directory