all: add minimal GoReleaser configuration for nightly builds
This is step one of many towards automated nightly releases.
This gets us downloadable binaries, which can be grabbed manually
from GitHub Releases...in theory, since this is untested,
because GitHub Actions.
Once this is working, future steps include:
- documentation
- homebrew support (and other package managers?)
- auto-updates
- installers
- blah blah blah
diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml
new file mode 100644
index 0000000..44494eb
--- /dev/null
+++ b/.github/workflows/release-build.yml
@@ -0,0 +1,101 @@
+name: Release Build (Nightly)
+
+on:
+ schedule:
+ - cron: "47 9 * * *" # 1:47 AM Pacific Time (9:47 UTC)
+ workflow_dispatch: # Allow manual triggering
+
+permissions:
+ contents: write
+
+jobs:
+ nightly:
+ runs-on: ubuntu-latest
+ if: github.ref == 'refs/heads/main'
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Set up Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: "20"
+ cache: "npm"
+ cache-dependency-path: "webui/package-lock.json"
+
+ - uses: actions/setup-go@v5
+ with:
+ go-version-file: "${{ inputs.working-directory || '.'}}/go.mod"
+ cache: true
+
+ - name: Check for changes since last tag
+ id: check_changes
+ run: |
+ git fetch --tags --force
+ # find latest nightly tag that looks like nightly/v0.0.N
+ latest_nightly=$(git tag -l "nightly/v0.0.*" --sort=-v:refname | head -n1)
+ if [ -z "$latest_nightly" ]; then
+ echo "has_changes=true" >> $GITHUB_OUTPUT
+ echo "tag=v0.0.1" >> $GITHUB_OUTPUT
+ echo "nightly_tag=nightly/v0.0.1" >> $GITHUB_OUTPUT
+ else
+ echo "Latest nightly tag is $latest_nightly"
+ # Check if there are any new commits since the last nightly tag
+ changes=$(git log $latest_nightly..HEAD --oneline)
+ if [ -z "$changes" ]; then
+ echo "No new changes since last nightly tag, skipping nightly build"
+ echo "has_changes=false" >> $GITHUB_OUTPUT
+ else
+ echo "Changes found since last nightly tag:"
+ echo "$changes"
+ echo "has_changes=true" >> $GITHUB_OUTPUT
+ # Extract N from nightly/v0.0.N and increment
+ version_part="${latest_nightly#nightly/v0.0.}"
+ new_n=$((version_part + 1))
+ new_tag="v0.0.${new_n}"
+ new_nightly_tag="nightly/v0.0.${new_n}"
+ echo "tag=$new_tag" >> $GITHUB_OUTPUT
+ echo "nightly_tag=$new_nightly_tag" >> $GITHUB_OUTPUT
+ fi
+ fi
+
+ - name: Create and push nightly git tag
+ if: steps.check_changes.outputs.has_changes == 'true'
+ env:
+ TAG: ${{ steps.check_changes.outputs.tag }}
+ NIGHTLY_TAG: ${{ steps.check_changes.outputs.nightly_tag }}
+ run: |
+ git config user.name "Sketch Nightly Bot"
+ git config user.email "hello@sketch.dev"
+ git tag -a "$TAG" -m "Nightly build $TAG"
+ git tag -a "$NIGHTLY_TAG" -m "Nightly build tracking tag for $TAG"
+ git push origin "$TAG"
+ git push origin "$NIGHTLY_TAG"
+
+ - name: Run GoReleaser (Nightly)
+ if: steps.check_changes.outputs.has_changes == 'true'
+ uses: goreleaser/goreleaser-action@v4
+ with:
+ version: latest
+ args: release --clean
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Mark release as prerelease
+ if: steps.check_changes.outputs.has_changes == 'true'
+ uses: actions/github-script@v6
+ with:
+ script: |
+ const tag = process.env.TAG;
+ const [owner, repo] = process.env.GITHUB_REPOSITORY.split('/');
+ const release = await github.rest.repos.getReleaseByTag({ owner, repo, tag });
+ await github.rest.repos.updateRelease({
+ owner,
+ repo,
+ release_id: release.data.id,
+ prerelease: true
+ });
+ env:
+ TAG: ${{ steps.check_changes.outputs.tag }}
diff --git a/.gitignore b/.gitignore
index 78d8a86..76fce36 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,6 @@
# Local environment variables
.envrc
+
+# goreleaser builds
+dist
diff --git a/.goreleaser.yml b/.goreleaser.yml
new file mode 100644
index 0000000..58f5bb6
--- /dev/null
+++ b/.goreleaser.yml
@@ -0,0 +1,37 @@
+version: 2
+project_name: sketch
+
+# Build configuration
+before:
+ hooks:
+ - "npm ci --prefix webui"
+ - "npm run build --prefix webui"
+
+builds:
+ - id: sketch
+ main: ./cmd/sketch
+ env:
+ - CGO_ENABLED=0
+ goos:
+ - linux
+ - darwin
+ goarch:
+ - amd64
+ - arm64
+ ldflags:
+ - -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}
+
+archives:
+ - id: releaseArchive
+ format: tar.gz
+ name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
+ files:
+ - README.md
+ - LICENSE
+
+release:
+ github:
+ owner: boldsoftware
+ name: sketch
+ draft: false
+ prerelease: false
diff --git a/cmd/sketch/main.go b/cmd/sketch/main.go
index 66fa115..e6e2d1e 100644
--- a/cmd/sketch/main.go
+++ b/cmd/sketch/main.go
@@ -40,6 +40,14 @@
"golang.org/x/term"
)
+// Version information set by GoReleaser at build time
+var (
+ version = "dev" // version string
+ commit = "none" // git commit hash
+ date = "unknown" // build timestamp
+ builtBy = "unknown" // who built this binary
+)
+
func main() {
err := run()
if err != nil {
@@ -59,9 +67,21 @@
}
if flagArgs.version {
+ fmt.Printf("sketch %s\n", version)
+
+ if commit != "none" {
+ fmt.Printf(" commit: %s\n", commit)
+ }
+ if date != "unknown" {
+ fmt.Printf(" built: %s\n", date)
+ }
+ if builtBy != "unknown" {
+ fmt.Printf(" by: %s\n", builtBy)
+ }
+
bi, ok := debug.ReadBuildInfo()
if ok {
- fmt.Printf("%s@%v\n", bi.Path, bi.Main.Version)
+ fmt.Printf(" buildinfo: %s@%v\n", bi.Path, bi.Main.Version)
}
return nil
}