vm-troubleshooting: defer File Transfer until auto-upload resolves; a… #8
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release gather-info | |
| on: | |
| push: | |
| tags: | |
| - "gather-info/v*" | |
| permissions: | |
| contents: write | |
| # working-directory applies to `run` steps only, not `uses` steps. | |
| # All `uses` step inputs (go-version-file, cache-dependency-path, files) | |
| # must use paths relative to the repository root. | |
| defaults: | |
| run: | |
| working-directory: customers/vm-troubleshooting | |
| jobs: | |
| release: | |
| runs-on: ubuntu-latest | |
| env: | |
| DO_SPACES_ENDPOINT: https://sfo3.digitaloceanspaces.com | |
| DO_SPACES_BUCKET: hyperstack-support-tools | |
| DO_SPACES_CDN: https://hyperstack-support-tools.sfo3.digitaloceanspaces.com | |
| AWS_DEFAULT_REGION: us-east-1 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version-file: customers/vm-troubleshooting/go.mod | |
| cache-dependency-path: customers/vm-troubleshooting/go.sum | |
| - name: Derive release metadata | |
| id: meta | |
| run: | | |
| VERSION="${GITHUB_REF_NAME#gather-info/}" | |
| BASENAME="gather-info-${VERSION}-linux-amd64" | |
| CHECKSUM_NAME="${BASENAME}.sha256" | |
| LATEST_NAME="gather-info-latest-linux-amd64" | |
| # Two release-info sidecars carry the version, binary URL, | |
| # and sha256 in the dashboard's release-info format: | |
| # release-${VERSION}-linux-amd64.txt — versioned, pinned | |
| # to this release. Use with -collector-release-file when | |
| # you want the dashboard to pin to a specific version. | |
| # release-latest-linux-amd64.txt — always overwritten by | |
| # the most recent successful release; this is what the | |
| # dashboard's default -collector-release-url polls. Its | |
| # `url=` line points at the immutable versioned binary, | |
| # not at the gather-info-latest-* alias, so the SHA in | |
| # the file always matches the bytes the customer would | |
| # download. | |
| RELEASE_NAME="release-${VERSION}-linux-amd64.txt" | |
| RELEASE_LATEST_NAME="release-latest-linux-amd64.txt" | |
| echo "version=${VERSION}" >> "$GITHUB_OUTPUT" | |
| echo "basename=${BASENAME}" >> "$GITHUB_OUTPUT" | |
| echo "checksum=${CHECKSUM_NAME}" >> "$GITHUB_OUTPUT" | |
| echo "latest=${LATEST_NAME}" >> "$GITHUB_OUTPUT" | |
| echo "release=${RELEASE_NAME}" >> "$GITHUB_OUTPUT" | |
| echo "release_latest=${RELEASE_LATEST_NAME}" >> "$GITHUB_OUTPUT" | |
| - name: Download modules | |
| run: go mod download | |
| - name: Vet | |
| run: go vet ./... | |
| - name: Test | |
| run: go test ./... | |
| - name: Build | |
| env: | |
| CGO_ENABLED: "0" | |
| GOOS: linux | |
| GOARCH: amd64 | |
| run: | | |
| VERSION="${{ steps.meta.outputs.version }}" | |
| COMMIT="${{ github.sha }}" | |
| DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)" | |
| OUTPUT="${{ steps.meta.outputs.basename }}" | |
| go build -trimpath \ | |
| -ldflags="-s -w \ | |
| -X github.com/NexGenCloud/vm-diagnostics/internal/config.Version=${VERSION} \ | |
| -X github.com/NexGenCloud/vm-diagnostics/internal/config.Commit=${COMMIT:0:7} \ | |
| -X github.com/NexGenCloud/vm-diagnostics/internal/config.BuildDate=${DATE}" \ | |
| -o "${OUTPUT}" \ | |
| ./cmd/gather-info | |
| - name: Generate checksum | |
| run: sha256sum "${{ steps.meta.outputs.basename }}" > "${{ steps.meta.outputs.checksum }}" | |
| - name: Generate release.txt sidecars | |
| run: | | |
| BINARY="${{ steps.meta.outputs.basename }}" | |
| VERSION="${{ steps.meta.outputs.version }}" | |
| RELEASE="${{ steps.meta.outputs.release }}" | |
| RELEASE_LATEST="${{ steps.meta.outputs.release_latest }}" | |
| SHA="$(sha256sum "${BINARY}" | awk '{print $1}')" | |
| URL="${DO_SPACES_CDN}/public/${BINARY}" | |
| { | |
| echo "version=${VERSION}" | |
| echo "url=${URL}" | |
| echo "sha256=${SHA}" | |
| } > "${RELEASE}" | |
| # Latest sidecar is byte-identical content to the versioned | |
| # one — having both makes pinning operators happy and keeps | |
| # the URL the dashboard polls stable across releases. | |
| cp "${RELEASE}" "${RELEASE_LATEST}" | |
| - name: Verify binary | |
| run: | | |
| ./"${{ steps.meta.outputs.basename }}" --version | |
| file "${{ steps.meta.outputs.basename }}" | grep -q "statically linked" | |
| - name: Generate changelog | |
| id: changelog | |
| working-directory: . | |
| run: | | |
| # Find the previous gather-info tag (excluding the current one) | |
| CURRENT_TAG="${GITHUB_REF_NAME}" | |
| PREV_TAG=$(git tag --list 'gather-info/v*' --sort=-version:refname \ | |
| | grep -v "^${CURRENT_TAG}$" | head -1) | |
| if [ -n "${PREV_TAG}" ]; then | |
| echo "Generating changelog: ${PREV_TAG}..${CURRENT_TAG}" | |
| CHANGES=$(git log --oneline --no-merges "${PREV_TAG}..${CURRENT_TAG}" \ | |
| -- customers/vm-troubleshooting/) | |
| else | |
| echo "No previous tag found — using all commits" | |
| CHANGES=$(git log --oneline --no-merges "${CURRENT_TAG}" \ | |
| -- customers/vm-troubleshooting/) | |
| fi | |
| # Write to file (multi-line output is tricky in GITHUB_OUTPUT) | |
| echo "${CHANGES}" > customers/vm-troubleshooting/changelog.txt | |
| echo "prev_tag=${PREV_TAG:-none}" >> "$GITHUB_OUTPUT" | |
| - name: Generate release body | |
| run: | | |
| VERSION="${{ steps.meta.outputs.version }}" | |
| BINARY="${{ steps.meta.outputs.basename }}" | |
| CHECKSUM="${{ steps.meta.outputs.checksum }}" | |
| CDN="${DO_SPACES_CDN}" | |
| PREV_TAG="${{ steps.changelog.outputs.prev_tag }}" | |
| # Build changelog section | |
| CHANGELOG="" | |
| if [ -s changelog.txt ]; then | |
| CHANGELOG="### Changes"$'\n\n' | |
| if [ "${PREV_TAG}" != "none" ]; then | |
| CHANGELOG="${CHANGELOG}Since \`${PREV_TAG}\`:"$'\n\n' | |
| fi | |
| while IFS= read -r line; do | |
| CHANGELOG="${CHANGELOG}- ${line}"$'\n' | |
| done < changelog.txt | |
| CHANGELOG="${CHANGELOG}"$'\n' | |
| fi | |
| cat > release-body.md <<BODY | |
| ## gather-info ${VERSION} | |
| ### Quick install | |
| \`\`\`bash | |
| curl -fSL "${CDN}/public/${BINARY}" -o gather-info | |
| curl -fSL "${CDN}/public/${CHECKSUM}" -o gather-info.sha256 | |
| sha256sum -c gather-info.sha256 | |
| chmod +x gather-info | |
| sudo ./gather-info | |
| \`\`\` | |
| ### Latest (always points to newest release) | |
| \`\`\`bash | |
| curl -fSL "${CDN}/public/gather-info-latest-linux-amd64" -o gather-info | |
| \`\`\` | |
| ${CHANGELOG}### What's included | |
| Static Linux x86_64 binary. Collects system, network, NVIDIA GPU, DCGM, Docker, services, journal, packages, storage, and InfiniBand diagnostics into a single \`.tar.gz\` archive. | |
| See [CODEMAP.md](https://github.com/${{ github.repository }}/blob/${{ github.sha }}/customers/vm-troubleshooting/CODEMAP.md) for architecture details. | |
| BODY | |
| sed -i 's/^ //' release-body.md | |
| - name: Create GitHub release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| name: "gather-info ${{ steps.meta.outputs.version }}" | |
| body_path: customers/vm-troubleshooting/release-body.md | |
| files: | | |
| customers/vm-troubleshooting/${{ steps.meta.outputs.basename }} | |
| customers/vm-troubleshooting/${{ steps.meta.outputs.checksum }} | |
| customers/vm-troubleshooting/${{ steps.meta.outputs.release }} | |
| customers/vm-troubleshooting/${{ steps.meta.outputs.release_latest }} | |
| - name: Upload to DigitalOcean Spaces | |
| env: | |
| AWS_ACCESS_KEY_ID: ${{ secrets.DO_SPACES_ACCESS_KEY_ID }} | |
| AWS_SECRET_ACCESS_KEY: ${{ secrets.DO_SPACES_SECRET_ACCESS_KEY }} | |
| run: | | |
| BINARY="${{ steps.meta.outputs.basename }}" | |
| CHECKSUM="${{ steps.meta.outputs.checksum }}" | |
| LATEST="${{ steps.meta.outputs.latest }}" | |
| S3_BASE="s3://${DO_SPACES_BUCKET}/public" | |
| S3_OPTS="--endpoint-url ${DO_SPACES_ENDPOINT} --region ${AWS_DEFAULT_REGION}" | |
| RELEASE="${{ steps.meta.outputs.release }}" | |
| RELEASE_LATEST="${{ steps.meta.outputs.release_latest }}" | |
| # Upload versioned binary + checksum + versioned + latest sidecar | |
| aws s3 cp "${BINARY}" "${S3_BASE}/${BINARY}" --acl public-read ${S3_OPTS} | |
| aws s3 cp "${CHECKSUM}" "${S3_BASE}/${CHECKSUM}" --acl public-read ${S3_OPTS} | |
| aws s3 cp "${RELEASE}" "${S3_BASE}/${RELEASE}" --acl public-read ${S3_OPTS} | |
| aws s3 cp "${RELEASE_LATEST}" "${S3_BASE}/${RELEASE_LATEST}" --acl public-read --cache-control "no-cache" ${S3_OPTS} | |
| # Update "latest" pointer (copy, not symlink — S3 doesn't support symlinks) | |
| aws s3 cp "${BINARY}" "${S3_BASE}/${LATEST}" --acl public-read ${S3_OPTS} | |
| echo "::notice::Binary: ${DO_SPACES_CDN}/public/${BINARY}" | |
| echo "::notice::Checksum: ${DO_SPACES_CDN}/public/${CHECKSUM}" | |
| echo "::notice::Release: ${DO_SPACES_CDN}/public/${RELEASE}" | |
| echo "::notice::Release-L: ${DO_SPACES_CDN}/public/${RELEASE_LATEST}" | |
| echo "::notice::Latest: ${DO_SPACES_CDN}/public/${LATEST}" |