Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
5 changes: 4 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,8 @@ jobs:
go-version-file: 'go.mod'
cache: true

- name: bootstrap
run: script/bootstrap

- name: build
run: go build -v ./cmd/gh-combine
run: script/build
3 changes: 3 additions & 0 deletions .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,8 @@ jobs:
go-version-file: 'go.mod'
cache: true

- name: bootstrap
run: script/bootstrap

- name: run golangci-lint
uses: golangci/golangci-lint-action@v8
3 changes: 3 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ jobs:
go-version-file: 'go.mod'
cache: true

- name: bootstrap
run: script/bootstrap

# Taken from https://github.com/cli/cli/blob/trunk/.github/workflows/lint.yml
- name: lint
run: |
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ jobs:
go-version-file: "go.mod"
cache: false

- name: bootstrap
run: script/bootstrap

- name: goreleaser
uses: goreleaser/goreleaser-action@9c156ee8a17a598857849441385a2041ef570552 # pin@v6
with:
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,8 @@ jobs:
go-version-file: 'go.mod'
cache: true

- name: bootstrap
run: script/bootstrap

- name: test
run: script/test
22 changes: 13 additions & 9 deletions internal/version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import (
)

var (
tag = "dev" // set via ldflags
commit = "123abc"
date = "now"
tag = "dev" // set via ldflags
commit = "123abc"
buildTime = "now"
)

const template = "%s (%s) built at %s\nhttps://github.com/github/gh-combine/releases/tag/%s"
Expand All @@ -22,18 +22,22 @@ func defaultBuildInfoReader() (*debug.BuildInfo, bool) {
}

func String() string {
info, ok := buildInfoReader()
// Start with ldflags values
currentCommit := commit
currentDate := buildTime

// Override with VCS info if available and ldflags weren't set
info, ok := buildInfoReader()
if ok {
for _, setting := range info.Settings {
if setting.Key == "vcs.revision" {
commit = setting.Value
if setting.Key == "vcs.revision" && commit == "123abc" {
currentCommit = setting.Value
}
if setting.Key == "vcs.time" {
date = setting.Value
if setting.Key == "vcs.time" && buildTime == "now" {
currentDate = setting.Value
}
}
}

return fmt.Sprintf(template, tag, commit, date, tag)
return fmt.Sprintf(template, tag, currentCommit, currentDate, tag)
}
42 changes: 35 additions & 7 deletions internal/version/version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ func TestString(t *testing.T) {
// Save original values
origTag := tag
origCommit := commit
origDate := date
origBuildTime := buildTime
origBuildInfoReader := buildInfoReader

// Restore original values after the test
defer func() {
tag = origTag
commit = origCommit
date = origDate
buildTime = origBuildTime
buildInfoReader = origBuildInfoReader
}()

Expand All @@ -25,7 +25,7 @@ func TestString(t *testing.T) {
// Set known values for testing
tag = "v1.0.0"
commit = "abc123"
date = "2025-04-15"
buildTime = "2025-04-15"

// Mock the buildInfoReader to return false so that preset values are used
buildInfoReader = func() (*debug.BuildInfo, bool) {
Expand All @@ -43,10 +43,10 @@ func TestString(t *testing.T) {

// Test 2: With mock build info that updates commit and date
t.Run("with mock build info", func(t *testing.T) {
// Set initial values
// Set sentinel values so VCS info will override
tag = "dev"
commit = "initial-commit"
date = "initial-date"
commit = "123abc"
buildTime = "now"

// Create mock build info with specific values
mockSettings := []debug.BuildSetting{
Expand Down Expand Up @@ -75,7 +75,7 @@ func TestString(t *testing.T) {
// Set initial values
tag = "dev"
commit = "unchanged-commit"
date = "unchanged-date"
buildTime = "unchanged-date"

// Empty build settings
buildInfoReader = func() (*debug.BuildInfo, bool) {
Expand All @@ -92,4 +92,32 @@ func TestString(t *testing.T) {
t.Errorf("Expected version string to be:\n%q\nbut got:\n%q", expected, result)
}
})

// Test 4: ldflags values should take precedence over VCS info
t.Run("ldflags precedence over vcs", func(t *testing.T) {
// Set non-sentinel values (simulating ldflags)
tag = "v2.0.0"
commit = "ldflags-commit"
buildTime = "ldflags-time"

// VCS info that should be ignored
mockSettings := []debug.BuildSetting{
{Key: "vcs.revision", Value: "vcs-commit-hash"},
{Key: "vcs.time", Value: "vcs-build-time"},
}

buildInfoReader = func() (*debug.BuildInfo, bool) {
return &debug.BuildInfo{
Settings: mockSettings,
}, true
}

result := String()

// ldflags values should be used, not VCS
expected := "v2.0.0 (ldflags-commit) built at ldflags-time\nhttps://github.com/github/gh-combine/releases/tag/v2.0.0"
if result != expected {
t.Errorf("Expected version string to be:\n%q\nbut got:\n%q", expected, result)
}
})
}
13 changes: 13 additions & 0 deletions script/bootstrap
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env bash

set -euo pipefail

source script/env "$@"

echo -e "${BLUE}🥾 Bootstrapping...${OFF}"

# Hermetic check: ensure all imports resolve from vendor/ only
# This avoids touching the network or the module cache.
go list -mod=vendor -deps ./... > /dev/null

echo -e "${GREEN}✅ Bootstrap complete!${OFF}"
13 changes: 13 additions & 0 deletions script/build
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env bash

set -euo pipefail

source script/env "$@"

# Get build information for embedding into binary
COMMIT_SHA="$(git rev-parse HEAD)"
BUILD_TIME="$(date -u '+%Y-%m-%dT%H:%M:%SZ')"

go build -mod=vendor -ldflags "-X github.com/github/gh-combine/internal/version.commit=${COMMIT_SHA} -X github.com/github/gh-combine/internal/version.buildTime=${BUILD_TIME}" -v ./cmd/gh-combine

echo -e "${GREEN}Build completed successfully!${OFF}"
49 changes: 49 additions & 0 deletions script/env
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#! /usr/bin/env bash

set -euo pipefail

# COLORS
export OFF='\033[0m'
export RED='\033[0;31m'
export GREEN='\033[0;32m'
export BLUE='\033[0;34m'
export PURPLE='\033[0;35m'

# set the working directory to the root of the project
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd .. && pwd )"
export DIR

# The name of the repository is the name of the directory (usually)
REPO_NAME=$(basename "$PWD")
export REPO_NAME

# detect OS version and architecture
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
PLATFORM="linux"
VERSION="$(awk -F= '/^VERSION_CODENAME=/{print $2}' /etc/os-release | tr -d '"' || echo "unknown")"
elif [[ "$OSTYPE" == "darwin"* ]]; then
PLATFORM="macos"
VERSION=$(sw_vers -productVersion || echo "unknown")
else
PLATFORM="unknown"
VERSION="unknown"
fi

ARCH=$(uname -m || echo "unknown")

export PLATFORM
export VERSION
export ARCH

# make the vendor/ directory if it doesn't exist
mkdir -p "$DIR/vendor/"

# Mark the current GitHub organization based on the remote URL
# This is used to set GOPRIVATE for private repositories
# You might want to remove these lines if you're not using a private repo in any of your dependencies
#CURRENT_GITHUB_ORG=$(git remote get-url origin | sed 's/.*github\.com[\/:]//; s/\/.*$//')
#export GOPRIVATE="github.com/$CURRENT_GITHUB_ORG/*"

# Set up Go environment variables
export GOPROXY="off"
export GOSUMDB="off"
9 changes: 5 additions & 4 deletions script/lint
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#! /usr/bin/env bash
#!/usr/bin/env bash

set -e
set -euo pipefail

go fmt ./...
go mod tidy
source script/env "$@"

go fmt -mod=vendor ./...
golangci-lint run --fix
4 changes: 3 additions & 1 deletion script/release
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#!/bin/bash
#!/usr/bin/env bash

set -euo pipefail

# Usage:
# script/release
Expand Down
10 changes: 6 additions & 4 deletions script/test
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
#! /usr/bin/env bash
#!/usr/bin/env bash

set -e
set -euo pipefail

source script/env "$@"

count=10

# if the tparse binary is not found, don't use it
if ! command -v tparse &> /dev/null; then
go test -race -count $count -v -cover -coverprofile=coverage.out ./...
go test -mod=vendor -race -count $count -v -cover -coverprofile=coverage.out ./...
else
set -o pipefail && go test -race -count $count -cover -coverprofile=coverage.out -json ./... | tparse -smallscreen -all -trimpath github.com/github/
set -o pipefail && go test -mod=vendor -race -count $count -cover -coverprofile=coverage.out -json ./... | tparse -smallscreen -all -trimpath github.com/github/
fi
43 changes: 43 additions & 0 deletions script/update
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env bash

set -euo pipefail

source script/env "$@"

# Always reset env on exit (success or failure)
restore_env() {
export GOPROXY="off"
export GOSUMDB="off"
}
trap restore_env EXIT

# Parse flags
ALL=0
for arg in "$@"; do
case "$arg" in
--all)
ALL=1
;;
esac
done

export GOPROXY="https://proxy.golang.org"
export GOSUMDB="sum.golang.org"
unset GOFLAGS # to avoid forcing -mod=vendor

# Update deps
if [ "$ALL" -eq 1 ]; then
echo -e "${BLUE}Updating ALL modules (direct + transitive)...${OFF}"
echo -e "${BLUE}Includes MAJOR version bumps (go get -u all).${OFF}"
go get -u all
else
echo -e "${BLUE}Updating direct deps to latest compatible versions...${OFF}"
echo -e "${BLUE}(minor/patch only; use --all for majors) (go get -u ./...).${OFF}"
go get -u ./...
fi

go mod tidy
go mod vendor
go mod verify

echo -e "${GREEN}Dependencies updated successfully!${OFF}"
Loading