Skip to content

vm-troubleshooting: defer File Transfer until auto-upload resolves; a… #8

vm-troubleshooting: defer File Transfer until auto-upload resolves; a…

vm-troubleshooting: defer File Transfer until auto-upload resolves; a… #8

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}"