Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/homebrew/bits.rb.erb
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
class Bits < Formula
desc "Datadog Assistant in your terminal"
homepage "https://github.com/datadog-labs/bits-cli"
# Shipped bits binaries read this line to offer updates; keep exactly one.
version "<%= values.fetch("version") %>"
license "Apache-2.0"
Comment thread
jinroh marked this conversation as resolved.

on_macos do
Expand Down
22 changes: 15 additions & 7 deletions internal/update/homebrew.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,16 +124,24 @@ func detectBackend(executable string) (backend, error) {
return h, nil
}

// Read only the explicit version declaration in our generated formula. This is
// deliberately not a Ruby parser; unexpected formats fail the check silently.
var formulaVersion = regexp.MustCompile(`(?m)^[\t ]*version[\t ]+"([^"\r\n]+)"[\t ]*\r?$`)
// Read the version from the release download URLs in our generated formula.
// Homebrew infers its formula version from these URLs, so avoid duplicating it
// in an explicit version stanza. This is deliberately not a Ruby parser;
// unexpected formats fail the check silently.
var formulaReleaseVersion = regexp.MustCompile(`(?m)^[\t ]*url[\t ]+"[^"\r\n]*/releases/download/v([^/"\r\n]+)/[^"\r\n]+"[\t ]*\r?$`)

func homebrewVersion(raw []byte) (string, error) {
matches := formulaVersion.FindAllSubmatch(raw, -1)
if len(matches) != 1 {
return "", fmt.Errorf("%w: expected one explicit Homebrew version", errInvalidVersion)
matches := formulaReleaseVersion.FindAllSubmatch(raw, -1)
if len(matches) == 0 {
return "", fmt.Errorf("%w: expected one version across Homebrew release URLs", errInvalidVersion)
}
latest := "v" + string(matches[0][1])
version := string(matches[0][1])
for _, match := range matches[1:] {
if string(match[1]) != version {
return "", fmt.Errorf("%w: mismatched versions across Homebrew release URLs", errInvalidVersion)
}
}
latest := "v" + version
if !semver.IsValid(latest) {
return "", fmt.Errorf("%w: Homebrew version %q", errInvalidVersion, latest)
}
Expand Down
13 changes: 6 additions & 7 deletions internal/update/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ func TestHomebrewFetch(t *testing.T) {
body, want string
invalid bool
}{
{"success", 200, ` version "1.3.0"`, "v1.3.0", false},
{"success", 200, ` url "https://github.com/datadog-labs/bits-cli/releases/download/v1.3.0/bits_1.3.0_linux_amd64.tar.gz"`, "v1.3.0", false},
{"server", 500, "", "", false},
{"missing", 404, "", "", false},
{"redirect", 302, "", "", false},
Expand Down Expand Up @@ -394,13 +394,12 @@ func TestHomebrewUpgrade(t *testing.T) {

func TestHomebrewVersion(t *testing.T) {
for _, tc := range []struct{ name, formula, want string }{
{"generated format", "class Bits < Formula\n version \"1.2.3\"\n on_macos do\n url \"https://example.com/v9.9.9/bits.tar.gz\"\n end\nend\n", "v1.2.3"},
{"windows newlines", " version \"1.2.3\"\r\n", "v1.2.3"},
{"generated format", "class Bits < Formula\n on_macos do\n url \"https://github.com/datadog-labs/bits-cli/releases/download/v1.2.3/bits_1.2.3_darwin_arm64.tar.gz\"\n url \"https://github.com/datadog-labs/bits-cli/releases/download/v1.2.3/bits_1.2.3_darwin_amd64.tar.gz\"\n end\nend\n", "v1.2.3"},
{"windows newlines", " url \"https://github.com/datadog-labs/bits-cli/releases/download/v1.2.3/bits_1.2.3_linux_amd64.tar.gz\"\r\n", "v1.2.3"},
{"missing", "class Bits < Formula\nend\n", ""},
{"comment", " # version \"1.2.3\"\n", ""},
{"duplicate", " version \"1.2.3\"\n version \"1.2.4\"\n", ""},
{"expression", " version ENV.fetch(\"VERSION\")\n", ""},
{"interpolation", " version \"#{version}\"\n", ""},
{"comment", " # url \"https://github.com/datadog-labs/bits-cli/releases/download/v1.2.3/bits_1.2.3_darwin_arm64.tar.gz\"\n", ""},
{"mismatched release URLs", " url \"https://github.com/datadog-labs/bits-cli/releases/download/v1.2.3/bits_1.2.3_darwin_arm64.tar.gz\"\n url \"https://github.com/datadog-labs/bits-cli/releases/download/v1.2.4/bits_1.2.4_linux_amd64.tar.gz\"\n", ""},
{"invalid version", " url \"https://github.com/datadog-labs/bits-cli/releases/download/vnot-a-version/bits.tar.gz\"\n", ""},
} {
t.Run(tc.name, func(t *testing.T) {
got, err := homebrewVersion([]byte(tc.formula))
Expand Down
4 changes: 2 additions & 2 deletions scripts/ciworkflow_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -290,8 +290,8 @@ func TestHomebrewTemplate(t *testing.T) {
if err != nil {
t.Fatalf("render formula: %v\n%s", err, formula)
}
if got := strings.Count(string(formula), "\n version \"1.2.3\"\n"); got != 1 {
t.Fatalf("expected one explicit version declaration, got %d", got)
if strings.Contains(string(formula), "\n version ") {
t.Fatal("formula should let Homebrew infer the version from its release URLs")
}
for _, platform := range platforms {
url := `url "https://github.com/datadog-labs/bits-cli/releases/download/v1.2.3/bits_1.2.3_` + platform + `.tar.gz"`
Expand Down
2 changes: 1 addition & 1 deletion scripts/try-update.sh
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ chmod +x "$PREFIX/bin/brew"

# Start without a cache so the first launch performs the real check.
rm -f "$STATE"
echo "--- serving $URL ($(grep -m1 '^ *version ' "$PREFIX/www/Formula/bits.rb" | xargs))"
echo "--- serving $URL ($(grep -m1 'releases/download/v' "$PREFIX/www/Formula/bits.rb" | sed -E 's|.*releases/download/(v[^/]+)/.*|\1|'))"

while true; do
echo "--- launching $("$PREFIX/bin/bits" --version)"
Expand Down
Loading