1 parent
5be86cbbd3
commit
80fad18437
5 files changed
+203
No files matched your search
@@ -0,0 +1,48 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main, master]
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GOPRIVATE: git.veillax.com
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version-file: go.mod
|
||||||
|
|
||||||
|
# Go fetches the other sharks modules straight from this server. This is harmless
|
||||||
|
# for public repositories and is what makes private ones work.
|
||||||
|
- name: Let Go fetch modules from this server
|
||||||
|
run: git config --global url."https://x-access-token:${{ secrets.GITHUB_TOKEN }}@git.veillax.com/".insteadOf "https://git.veillax.com/"
|
||||||
|
|
||||||
|
- name: Formatting
|
||||||
|
run: |
|
||||||
|
unformatted=$(gofmt -l .)
|
||||||
|
if [ -n "$unformatted" ]; then
|
||||||
|
echo "These files need gofmt:"
|
||||||
|
echo "$unformatted"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Vet
|
||||||
|
run: go vet ./...
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: go test ./...
|
||||||
|
|
||||||
|
# Catches platform-specific breakage before a release is tagged.
|
||||||
|
- name: Every release platform compiles
|
||||||
|
run: |
|
||||||
|
for t in linux/amd64 windows/amd64; do
|
||||||
|
for c in hhctl terraform-provider-hammerhead; do
|
||||||
|
echo "building $c for $t"
|
||||||
|
GOOS=${t%/*} GOARCH=${t#*/} CGO_ENABLED=0 go build -o /dev/null ./cmd/$c
|
||||||
|
done
|
||||||
|
done
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
name: Release
|
||||||
|
|
||||||
|
# Push a tag such as v0.2.0 to build and publish a release:
|
||||||
|
# git tag -a v0.2.0 -m "hhctl v0.2.0" && git push origin v0.2.0
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags: ['v*']
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GOPRIVATE: git.veillax.com
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # release notes come from the history since the previous tag
|
||||||
|
|
||||||
|
- uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version-file: go.mod
|
||||||
|
|
||||||
|
- name: Let Go fetch modules from this server
|
||||||
|
run: git config --global url."https://x-access-token:${{ secrets.GITHUB_TOKEN }}@git.veillax.com/".insteadOf "https://git.veillax.com/"
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: |
|
||||||
|
go vet ./...
|
||||||
|
go test ./...
|
||||||
|
|
||||||
|
- name: Build release archives
|
||||||
|
run: sh deploy/build.sh "${GITHUB_REF_NAME}"
|
||||||
|
|
||||||
|
# Optional secret RELEASE_TOKEN: an access token that can write releases, for
|
||||||
|
# servers where the automatic job token can't.
|
||||||
|
- name: Publish the release
|
||||||
|
env:
|
||||||
|
TOKEN: ${{ secrets.RELEASE_TOKEN || secrets.GITHUB_TOKEN }}
|
||||||
|
run: sh deploy/publish-release.sh "${GITHUB_REF_NAME}"
|
||||||
@@ -2,3 +2,4 @@
|
|||||||
*.exe
|
*.exe
|
||||||
.terraform*
|
.terraform*
|
||||||
*.tfstate*
|
*.tfstate*
|
||||||
|
dist/
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Builds hhctl for every release platform and packs the archives into dist/.
|
||||||
|
#
|
||||||
|
# deploy/build.sh [version] version defaults to `git describe`
|
||||||
|
#
|
||||||
|
# Output:
|
||||||
|
# dist/hhctl_<version>_<os>_<arch>.tar.gz or .zip
|
||||||
|
# dist/SHA256SUMS
|
||||||
|
#
|
||||||
|
# Releases are published for linux/amd64 and windows/amd64 only. Set TARGETS="linux/arm64 darwin/arm64"
|
||||||
|
# (any GOOS/GOARCH pair Go supports) to build something else by hand.
|
||||||
|
set -eu
|
||||||
|
NAME=hhctl
|
||||||
|
CMDS="hhctl terraform-provider-hammerhead"
|
||||||
|
cd "$(dirname "$0")/.."
|
||||||
|
VERSION=${1:-$(git describe --tags --always 2>/dev/null || echo dev)}
|
||||||
|
TARGETS=${TARGETS:-"linux/amd64 windows/amd64"}
|
||||||
|
|
||||||
|
rm -rf dist
|
||||||
|
mkdir -p dist/stage
|
||||||
|
for t in $TARGETS; do
|
||||||
|
os=${t%/*}
|
||||||
|
arch=${t#*/}
|
||||||
|
ext=""
|
||||||
|
[ "$os" = windows ] && ext=".exe"
|
||||||
|
pkg="${NAME}_${VERSION}_${os}_${arch}"
|
||||||
|
stage="dist/stage/$pkg"
|
||||||
|
mkdir -p "$stage"
|
||||||
|
for c in $CMDS; do
|
||||||
|
echo "building $c $VERSION for $os/$arch"
|
||||||
|
CGO_ENABLED=0 GOOS=$os GOARCH=$arch go build -trimpath -ldflags "-s -w -X main.version=$VERSION" -o "$stage/$c$ext" "./cmd/$c"
|
||||||
|
done
|
||||||
|
for f in LICENSE README.md; do
|
||||||
|
[ -f "$f" ] && cp "$f" "$stage/"
|
||||||
|
done
|
||||||
|
if [ "$os" = windows ] && command -v zip >/dev/null 2>&1; then
|
||||||
|
(cd dist/stage && zip -qr "../$pkg.zip" "$pkg")
|
||||||
|
else
|
||||||
|
tar -C dist/stage -czf "dist/$pkg.tar.gz" "$pkg"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
rm -rf dist/stage
|
||||||
|
(cd dist && sha256sum $(ls | grep -E '\.(tar\.gz|zip)$') > SHA256SUMS)
|
||||||
|
echo "done: $(ls dist | grep -cE '\.(tar\.gz|zip)$') archives in dist/"
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Creates (or updates) the Gitea release for a tag and uploads what deploy/build.sh made.
|
||||||
|
#
|
||||||
|
# TOKEN=<access token that can write releases> deploy/publish-release.sh v0.2.0
|
||||||
|
#
|
||||||
|
# In Gitea Actions GITHUB_SERVER_URL and GITHUB_REPOSITORY are already set. Safe to
|
||||||
|
# re-run: an existing release is reused and assets with the same name are replaced.
|
||||||
|
set -eu
|
||||||
|
TAG=${1:?usage: publish-release.sh <tag>}
|
||||||
|
: "${TOKEN:?set TOKEN to a Gitea access token that can write releases}"
|
||||||
|
SERVER=${GITHUB_SERVER_URL:-${GITEA_SERVER_URL:-https://git.veillax.com}}
|
||||||
|
REPO=${GITHUB_REPOSITORY:-Veillax/hhctl}
|
||||||
|
API="$SERVER/api/v1/repos/$REPO"
|
||||||
|
AUTH="Authorization: token $TOKEN"
|
||||||
|
|
||||||
|
# a JSON helper without needing jq: any python will do
|
||||||
|
PY=python3
|
||||||
|
python3 -c 'pass' > /dev/null 2>&1 || PY=python
|
||||||
|
json() { "$PY" -c "$1"; }
|
||||||
|
|
||||||
|
# release notes: the commit subjects since the previous tag
|
||||||
|
prev=$(git describe --tags --abbrev=0 "$TAG^" 2>/dev/null || true)
|
||||||
|
if [ -n "$prev" ]; then
|
||||||
|
notes=$(git log --pretty='format:- %s' "$prev..$TAG")
|
||||||
|
else
|
||||||
|
notes=$(git log --pretty='format:- %s' "$TAG")
|
||||||
|
fi
|
||||||
|
prerelease=false
|
||||||
|
case "$TAG" in *-*) prerelease=true ;; esac
|
||||||
|
|
||||||
|
body=$(NOTES="$notes" TAG="$TAG" PRE="$prerelease" json '
|
||||||
|
import json, os
|
||||||
|
print(json.dumps({"tag_name": os.environ["TAG"], "name": os.environ["TAG"], "body": os.environ["NOTES"],
|
||||||
|
"draft": False, "prerelease": os.environ["PRE"] == "true"}))')
|
||||||
|
|
||||||
|
# reuse the release when a failed job is re-run
|
||||||
|
id=$(curl -fsS -H "$AUTH" "$API/releases/tags/$TAG" 2>/dev/null | json 'import sys, json; print(json.load(sys.stdin)["id"])' 2>/dev/null || true)
|
||||||
|
if [ -z "$id" ]; then
|
||||||
|
echo "creating release $TAG"
|
||||||
|
id=$(curl -fsS -X POST -H "$AUTH" -H 'Content-Type: application/json' -d "$body" "$API/releases" | json 'import sys, json; print(json.load(sys.stdin)["id"])')
|
||||||
|
else
|
||||||
|
echo "release $TAG already exists (id $id): replacing its files"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# the ids of the release's assets with a given name (a failed upload can leave a partial one behind)
|
||||||
|
asset_ids() {
|
||||||
|
curl -fsS -H "$AUTH" "$API/releases/$id/assets" | "$PY" -c 'import sys, json
|
||||||
|
for a in json.load(sys.stdin):
|
||||||
|
if a["name"] == sys.argv[1]:
|
||||||
|
print(a["id"])' "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
for f in dist/*.tar.gz dist/*.zip dist/SHA256SUMS; do
|
||||||
|
[ -f "$f" ] || continue
|
||||||
|
name=$(basename "$f")
|
||||||
|
n=1
|
||||||
|
while :; do
|
||||||
|
for aid in $(asset_ids "$name"); do
|
||||||
|
curl -fsS -X DELETE -H "$AUTH" "$API/releases/$id/assets/$aid" > /dev/null
|
||||||
|
done
|
||||||
|
echo "uploading $name (attempt $n)"
|
||||||
|
if curl -fsS --max-time 1200 -X POST -H "$AUTH" -F "attachment=@$f" "$API/releases/$id/assets?name=$name" > /dev/null; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
# large uploads can hit a proxy timeout (HTTP 502); try again
|
||||||
|
[ "$n" -lt 5 ] || { echo "giving up on $name after $n attempts" >&2; exit 1; }
|
||||||
|
n=$((n + 1))
|
||||||
|
sleep $((n * 10))
|
||||||
|
done
|
||||||
|
done
|
||||||
|
echo "published $SERVER/$REPO/releases/tag/$TAG"
|
||||||
Reference in new issue
Block a user