name: Release on: push: tags: - 'v*' workflow_dispatch: inputs: tag: description: 'Tag to release (e.g. v1.2.3)' required: true jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version-file: go.mod - name: Test run: go test ./... - name: Lint run: go vet ./... release: needs: test runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: actions/setup-go@v5 with: go-version-file: go.mod - name: Build release binaries run: | VERSION="${{ github.event.inputs.tag || github.ref_name }}" for target in "linux/amd64" "linux/arm64" "darwin/amd64" "darwin/arm64" "windows/amd64"; do GOOS="${target%/*}" GOARCH="${target#*/}" EXT="" [ "$GOOS" = "windows" ] && EXT=".exe" NAME="unitdore-${GOOS}-${GOARCH}${EXT}" GOOS="$GOOS" GOARCH="$GOARCH" go build \ -ldflags "-X main.version=${VERSION}" \ -o "$NAME" . echo "Built $NAME" done - name: Create release and upload assets run: | TAG="${{ github.event.inputs.tag || github.ref_name }}" API="${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/releases" # Collect commits since the previous tag (or last 20 if no prior tag) PREV_TAG=$(git tag --sort=-version:refname | grep -v "^${TAG}$" | head -1) if [ -n "$PREV_TAG" ]; then RANGE="${PREV_TAG}..${TAG}" else RANGE="HEAD~20..HEAD" fi NOTES=$(git log "$RANGE" --pretty=format:"- %s" --no-merges) BODY="## What's changed"$'\n'"${NOTES}" # Escape for JSON BODY_JSON=$(printf '%s' "$BODY" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read()))') RELEASE=$(curl -s -X POST "$API" \ -H "Authorization: token ${GITHUB_TOKEN}" \ -H "Content-Type: application/json" \ -d "{\"tag_name\":\"${TAG}\",\"name\":\"${TAG}\",\"body\":${BODY_JSON}}") UPLOAD_URL=$(echo "$RELEASE" | grep -o '"upload_url":"[^"]*"' | cut -d'"' -f4) if [ -z "$UPLOAD_URL" ]; then echo "Failed to create release: $RELEASE" exit 1 fi for f in unitdore-*; do echo "Uploading $f..." curl -s -X POST "${UPLOAD_URL}?name=${f}" \ -H "Authorization: token ${GITHUB_TOKEN}" \ -H "Content-Type: application/octet-stream" \ --data-binary "@${f}" > /dev/null done env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} pkg-arch: needs: release runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Build Arch package run: | VERSION="${{ github.event.inputs.tag || github.ref_name }}" PKGVER="${VERSION#v}" # Source tarball — prefix=unitdore/ matches `cd "$pkgname"` in PKGBUILD git archive --format=tar.gz --prefix=unitdore/ HEAD \ > pkg/arch/unitdore-${PKGVER}.tar.gz SHA=$(sha256sum pkg/arch/unitdore-${PKGVER}.tar.gz | cut -d' ' -f1) # Patch PKGBUILD for local build sed -i \ -e "s/^pkgver=.*/pkgver=${PKGVER}/" \ -e "s/^sha256sums=.*/sha256sums=('${SHA}')/" \ -e "s|source=.*|source=(\"unitdore-\${pkgver}.tar.gz\")|" \ pkg/arch/PKGBUILD mkdir -p pkg/arch/out docker run --rm \ -v "$PWD/pkg/arch:/build" \ -v "$PWD/pkg/arch/out:/out" \ -w /build \ archlinux:latest \ bash -c " pacman -Syu --noconfirm base-devel go && useradd -m builder && chown -R builder:builder /build && runuser -u builder -- makepkg --noconfirm --noprogressbar && cp /build/*.pkg.tar.zst /out/ " - name: Upload to release run: | TAG="${{ github.event.inputs.tag || github.ref_name }}" RELEASE=$(curl -s "${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/releases/tags/${TAG}" \ -H "Authorization: token ${GITHUB_TOKEN}") UPLOAD_URL=$(echo "$RELEASE" | grep -o '"upload_url":"[^"]*"' | cut -d'"' -f4) for f in pkg/arch/out/*.pkg.tar.zst; do FNAME=$(basename "$f") echo "Uploading $FNAME..." curl -s -X POST "${UPLOAD_URL}?name=${FNAME}" \ -H "Authorization: token ${GITHUB_TOKEN}" \ -H "Content-Type: application/octet-stream" \ --data-binary "@${f}" > /dev/null done env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} pkg-deb: needs: release runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: actions/setup-go@v5 with: go-version-file: go.mod - name: Build Debian packages run: | VERSION="${{ github.event.inputs.tag || github.ref_name }}" PKGVER="${VERSION#v}" for GOARCH in amd64 arm64; do GOOS=linux GOARCH=$GOARCH go build \ -trimpath \ -ldflags "-X main.version=${PKGVER}" \ -o unitdore . PKGDIR="unitdore_${PKGVER}_${GOARCH}" mkdir -p "${PKGDIR}/DEBIAN" mkdir -p "${PKGDIR}/usr/bin" mkdir -p "${PKGDIR}/usr/share/man/man1" mkdir -p "${PKGDIR}/etc/unitdore" install -m755 unitdore "${PKGDIR}/usr/bin/unitdore" install -m644 docs/unitdore.1 "${PKGDIR}/usr/share/man/man1/unitdore.1" sed -e "s/VERSION/${PKGVER}/" \ -e "s/ARCH/${GOARCH}/" \ pkg/debian/control > "${PKGDIR}/DEBIAN/control" dpkg-deb --build --root-owner-group "${PKGDIR}" echo "Built ${PKGDIR}.deb" done - name: Upload to release run: | TAG="${{ github.event.inputs.tag || github.ref_name }}" RELEASE=$(curl -s "${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/releases/tags/${TAG}" \ -H "Authorization: token ${GITHUB_TOKEN}") UPLOAD_URL=$(echo "$RELEASE" | grep -o '"upload_url":"[^"]*"' | cut -d'"' -f4) for f in *.deb; do FNAME=$(basename "$f") echo "Uploading $FNAME..." curl -s -X POST "${UPLOAD_URL}?name=${FNAME}" \ -H "Authorization: token ${GITHUB_TOKEN}" \ -H "Content-Type: application/octet-stream" \ --data-binary "@${f}" > /dev/null done env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} pkg-rpm: needs: release runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Build RPM run: | VERSION="${{ github.event.inputs.tag || github.ref_name }}" PKGVER="${VERSION#v}" # Source tarball — prefix=unitdore-VERSION/ matches RPM %autosetup convention git archive --format=tar.gz --prefix=unitdore-${PKGVER}/ HEAD \ > unitdore-${PKGVER}.tar.gz # Patch spec version sed -i "s/^Version:.*/Version: ${PKGVER}/" pkg/centos/unitdore.spec mkdir -p pkg/centos/out docker run --rm \ -v "$PWD:/workspace" \ -v "$PWD/pkg/centos/out:/out" \ -w /workspace \ rockylinux:9 \ bash -c " dnf install -y rpm-build golang git && mkdir -p ~/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS} && cp unitdore-${PKGVER}.tar.gz ~/rpmbuild/SOURCES/ && cp pkg/centos/unitdore.spec ~/rpmbuild/SPECS/ && rpmbuild -ba ~/rpmbuild/SPECS/unitdore.spec && find ~/rpmbuild/RPMS -name '*.rpm' -exec cp {} /out/ \; " - name: Upload to release run: | TAG="${{ github.event.inputs.tag || github.ref_name }}" RELEASE=$(curl -s "${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/releases/tags/${TAG}" \ -H "Authorization: token ${GITHUB_TOKEN}") UPLOAD_URL=$(echo "$RELEASE" | grep -o '"upload_url":"[^"]*"' | cut -d'"' -f4) for f in pkg/centos/out/*.rpm; do FNAME=$(basename "$f") echo "Uploading $FNAME..." curl -s -X POST "${UPLOAD_URL}?name=${FNAME}" \ -H "Authorization: token ${GITHUB_TOKEN}" \ -H "Content-Type: application/octet-stream" \ --data-binary "@${f}" > /dev/null done env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}