-
Notifications
You must be signed in to change notification settings - Fork 1
Add release automation and installation tooling #19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| name: Release | ||
|
|
||
| on: | ||
| push: | ||
| tags: | ||
| - 'v*' | ||
|
|
||
| permissions: | ||
| contents: write | ||
| packages: write | ||
|
|
||
| jobs: | ||
| release: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 | ||
|
|
||
| - name: Set up Go | ||
| uses: actions/setup-go@v5 | ||
| with: | ||
| go-version-file: go.mod | ||
|
|
||
| - name: Set up Go module cache | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: | | ||
| ~/.cache/go-build | ||
| ~/go/pkg/mod | ||
| key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} | ||
| restore-keys: | | ||
| ${{ runner.os }}-go- | ||
|
|
||
| - name: Install GoReleaser | ||
| uses: goreleaser/goreleaser-action@v6 | ||
| with: | ||
| version: latest | ||
| distribution: goreleaser | ||
| install-only: true | ||
|
|
||
| - name: Run GoReleaser | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: goreleaser release --clean |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| project_name: devx | ||
| before: | ||
| hooks: | ||
| - go test ./... | ||
|
|
||
| builds: | ||
| - id: devx | ||
| main: ./main.go | ||
| binary: devx | ||
| env: | ||
| - CGO_ENABLED=0 | ||
| goos: | ||
| - darwin | ||
| - linux | ||
| goarch: | ||
| - amd64 | ||
| - arm64 | ||
| ldflags: | ||
| - -s -w | ||
| - -X github.com/jfox85/devx/version.Version={{.Version}} | ||
| - -X github.com/jfox85/devx/version.GitCommit={{.ShortCommit}} | ||
| - -X github.com/jfox85/devx/version.BuildDate={{.Date}} | ||
|
|
||
| archives: | ||
| - format: tar.gz | ||
| name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}" | ||
| files: | ||
| - LICENSE | ||
| - README.md | ||
| strip_parent_binary_folder: true | ||
| wrap_in_directory: false | ||
|
|
||
| checksums: | ||
| name_template: "checksums.txt" | ||
|
|
||
| snapshot: | ||
| name_template: "{{ .Tag }}-SNAPSHOT" | ||
|
|
||
| changelog: | ||
| use: git | ||
|
|
||
| brews: | ||
| - name: devx | ||
| homepage: https://github.com/jfox85/devx | ||
| description: "A macOS development environment manager" | ||
| license: "MIT" | ||
| commit_author: | ||
| name: devx-bot | ||
| email: devx@jonefox.com | ||
| tap: | ||
| owner: jfox85 | ||
| name: homebrew-devx | ||
| test: | | ||
| system "#{bin}/devx", "--version" | ||
| install: | | ||
| bin.install "devx" | ||
| dependencies: | ||
| - name: go | ||
| type: optional | ||
|
|
||
| announce: | ||
| skip: true | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| <!DOCTYPE html> | ||
| <html lang="en"> | ||
| <head> | ||
| <meta charset="utf-8" /> | ||
| <meta http-equiv="refresh" content="0;url=https://raw.githubusercontent.com/jfox85/devx/main/install/install.sh" /> | ||
| <title>Install devx</title> | ||
| </head> | ||
| <body> | ||
| <p> | ||
| Redirecting to the latest install script. If you are not automatically redirected, | ||
| <a href="https://raw.githubusercontent.com/jfox85/devx/main/install/install.sh">click here</a>. | ||
| </p> | ||
| </body> | ||
| </html> |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,81 @@ | ||||||||||||||||||||||||||||||||
| #!/usr/bin/env bash | ||||||||||||||||||||||||||||||||
| set -euo pipefail | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| REPO="jfox85/devx" | ||||||||||||||||||||||||||||||||
| INSTALL_DIR="${DEVX_INSTALL_DIR:-/usr/local/bin}" | ||||||||||||||||||||||||||||||||
| VERSION="${DEVX_VERSION:-latest}" | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| usage() { | ||||||||||||||||||||||||||||||||
| cat <<USAGE | ||||||||||||||||||||||||||||||||
| Install devx from GitHub releases. | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| Environment variables: | ||||||||||||||||||||||||||||||||
| DEVX_VERSION Specific version (defaults to latest release) | ||||||||||||||||||||||||||||||||
| DEVX_INSTALL_DIR Target directory for the devx binary (default: /usr/local/bin) | ||||||||||||||||||||||||||||||||
| USAGE | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| command -v curl >/dev/null 2>&1 || { echo "curl is required to install devx" >&2; exit 1; } | ||||||||||||||||||||||||||||||||
| command -v tar >/dev/null 2>&1 || { echo "tar is required to install devx" >&2; exit 1; } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then | ||||||||||||||||||||||||||||||||
| usage | ||||||||||||||||||||||||||||||||
| exit 0 | ||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| os="$(uname -s | tr '[:upper:]' '[:lower:]')" | ||||||||||||||||||||||||||||||||
| arch="$(uname -m)" | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| case "$os" in | ||||||||||||||||||||||||||||||||
| linux|darwin) | ||||||||||||||||||||||||||||||||
| ;; | ||||||||||||||||||||||||||||||||
| *) | ||||||||||||||||||||||||||||||||
| echo "Unsupported operating system: $os" >&2 | ||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||
| ;; | ||||||||||||||||||||||||||||||||
| esac | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| case "$arch" in | ||||||||||||||||||||||||||||||||
| x86_64|amd64) | ||||||||||||||||||||||||||||||||
| arch="amd64" | ||||||||||||||||||||||||||||||||
| ;; | ||||||||||||||||||||||||||||||||
| arm64|aarch64) | ||||||||||||||||||||||||||||||||
| arch="arm64" | ||||||||||||||||||||||||||||||||
| ;; | ||||||||||||||||||||||||||||||||
| *) | ||||||||||||||||||||||||||||||||
| echo "Unsupported architecture: $arch" >&2 | ||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||
| ;; | ||||||||||||||||||||||||||||||||
| esac | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| if [[ "$VERSION" == "latest" ]]; then | ||||||||||||||||||||||||||||||||
| VERSION="$(curl -fsSL "https://api.github.com/repos/${REPO}/releases/latest" | \ | ||||||||||||||||||||||||||||||||
| grep -m1 '"tag_name"' | sed -E 's/.*"([^"]+)".*/\1/')" | ||||||||||||||||||||||||||||||||
| if [[ -z "$VERSION" ]]; then | ||||||||||||||||||||||||||||||||
| echo "Unable to determine latest release version" >&2 | ||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||
| if [[ "$VERSION" != v* ]]; then | ||||||||||||||||||||||||||||||||
| VERSION="v${VERSION}" | ||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| asset_version="${VERSION#v}" | ||||||||||||||||||||||||||||||||
| asset="devx_${asset_version}_${os}_${arch}.tar.gz" | ||||||||||||||||||||||||||||||||
| url="https://github.com/${REPO}/releases/download/${VERSION}/${asset}" | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| workdir="$(mktemp -d)" | ||||||||||||||||||||||||||||||||
| trap 'rm -rf "$workdir"' EXIT | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| echo "Downloading ${asset}..." | ||||||||||||||||||||||||||||||||
| curl -fsSL "${url}" -o "${workdir}/${asset}" | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| echo "Extracting devx..." | ||||||||||||||||||||||||||||||||
| tar -xzf "${workdir}/${asset}" -C "${workdir}" | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| mkdir -p "${INSTALL_DIR}" | ||||||||||||||||||||||||||||||||
| install -m 0755 "${workdir}/devx" "${INSTALL_DIR}/devx" | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
|
Comment on lines
+74
to
+79
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major 🧩 Analysis chainDon’t assume archive layout; make extraction robust. If the archive contains a leading directory (common with GoReleaser), Apply: -echo "Extracting devx..."
-tar -xzf "${workdir}/${asset}" -C "${workdir}"
-
-mkdir -p "${INSTALL_DIR}"
-install -m 0755 "${workdir}/devx" "${INSTALL_DIR}/devx"
+echo "Extracting devx..."
+tar -xzf "${workdir}/${asset}" -C "${workdir}"
+# Find the devx binary regardless of archive layout (flat or nested)
+bin_path="$(cd "${workdir}" && find . -type f -name devx -perm -u+x -print -quit)"
+if [[ -z "${bin_path}" ]]; then
+ echo "devx binary not found in archive" >&2
+ exit 1
+fi
+mkdir -p "${INSTALL_DIR}"
+install -m 0755 "${workdir}/${bin_path#./}" "${INSTALL_DIR}/devx"If your GoReleaser archives are guaranteed flat, confirm and we can keep the current approach. Otherwise, this makes installs resilient. 🏁 Script executed: #!/bin/bash
grep -R -n "asset=" install/install.sh
sed -n '1,200p' install/install.sh
grep -R -n "GoReleaser" .Length of output: 2069 Don’t assume flat archive layout; locate the binary dynamically GoReleaser’s tar.gz archives include a top-level directory by default, so -echo "Extracting devx..."
-tar -xzf "${workdir}/${asset}" -C "${workdir}"
-
-mkdir -p "${INSTALL_DIR}"
-install -m 0755 "${workdir}/devx" "${INSTALL_DIR}/devx"
+echo "Extracting devx..."
+tar -xzf "${workdir}/${asset}" -C "${workdir}"
+# Find the devx binary regardless of archive layout
+bin_path="$(cd "${workdir}" && find . -type f -name devx -perm -u+x -print -quit)"
+if [[ -z "${bin_path}" ]]; then
+ echo "devx binary not found in archive" >&2
+ exit 1
+fi
+mkdir -p "${INSTALL_DIR}"
+install -m 0755 "${workdir}/${bin_path#./}" "${INSTALL_DIR}/devx"install/install.sh:74-79 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||
| echo "devx installed to ${INSTALL_DIR}/devx" | ||||||||||||||||||||||||||||||||
| "${INSTALL_DIR}/devx" --version || true | ||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Point the Homebrew tap at the correct repository
Lines 51‑52 set the tap to
toneclone/toneclone, but the Homebrew tap repo is typicallytoneclone/homebrew-toneclone(matching the documentedbrew tap toneclone/toneclone, which strips thehomebrew-prefix). GoReleaser expects the actual GitHub repo name here; with the current value it will try to push the formula togithub.com/toneclone/toneclone, so tap updates will fail. Update the tap name to the real repo.brews: - name: devx homepage: https://github.com/jfox85/devx description: "A macOS development environment manager" license: "MIT" commit_author: name: toneclone-bot email: opensource@toneclone.dev tap: owner: toneclone - name: toneclone + name: homebrew-toneclone📝 Committable suggestion
🤖 Prompt for AI Agents