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
105 changes: 103 additions & 2 deletions .github/workflows/go-getter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ env:

jobs:

# Basic validation that runs on both PRs and pushes (safe operations)
basic-validation:
# Linux basic validation that runs on both PRs and pushes (safe operations)
linux-basic-validation:
runs-on: ubuntu-latest
strategy:
matrix:
Expand Down Expand Up @@ -56,6 +56,104 @@ jobs:
- name: Run unit tests (without cloud integration)
run: go test -short -v ./...

# Windows basic validation that runs on both PRs and pushes (safe operations)
windows-basic-validation:
runs-on: windows-latest
strategy:
matrix:
go-version:
- "1.24"
- "1.25"
steps:
- name: Run git config # Windows-only
run: git config --global core.autocrlf false

- name: Setup go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: ${{ matrix.go-version }}

- name: Checkout code
uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v4.0.0

- name: Setup cache for go modules
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
with:
path: |
~\AppData\Local\go-build
~\go\pkg\mod
key: ${{ runner.os }}-go${{ matrix.go-version }}-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go${{ matrix.go-version }}-
${{ runner.os }}-go-

# Check go fmt output because it does not report non-zero when there are fmt changes
- name: Run gofmt
shell: bash
run: |
go fmt ./...
files=$(go fmt ./...)
if [ -n "$files" ]; then
echo "The following file(s) do not conform to go fmt:"
echo "$files"
exit 1
fi

- name: Build all packages
run: go build ./...

- name: Run unit tests (without cloud integration)
run: go test -short -v ./...

# 32-bit architecture compatibility test to catch overflow issues
architecture-compatibility:
runs-on: ubuntu-latest
strategy:
matrix:
go-version:
- "1.24"
- "1.25"
arch:
- "386" # 32-bit x86
- "arm" # 32-bit ARM
steps:
- name: Setup go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: ${{ matrix.go-version }}

- name: Checkout code
uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v4.0.0

- name: Setup cache for go modules
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go${{ matrix.go-version }}-${{ matrix.arch }}-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go${{ matrix.go-version }}-${{ matrix.arch }}-
${{ runner.os }}-go${{ matrix.go-version }}-
${{ runner.os }}-go-

- name: Build for ${{ matrix.arch }}
env:
GOOS: linux
GOARCH: ${{ matrix.arch }}
run: go build ./...

- name: Test for ${{ matrix.arch }} (build only - no execution)
env:
GOOS: linux
GOARCH: ${{ matrix.arch }}
run: |
# Test compile each package individually to avoid binary naming conflicts
for pkg in $(go list ./...); do
echo "Testing compilation for $pkg on ${{ matrix.arch }}"
go test -c "$pkg"
done

# Linter runs on both PRs and pushes (safe operation)
linter:
runs-on: ubuntu-latest
Expand All @@ -82,6 +180,9 @@ jobs:
- name: Lint code
uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 # v8.0.0

- name: Check for modern Go patterns
run: go run golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@latest -test ./...

# Full integration tests with cloud resources (only on push to protected branches)
linux-integration-tests:
runs-on: ubuntu-latest
Expand Down
41 changes: 23 additions & 18 deletions get_file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package getter
import (
"os"
"path/filepath"
"runtime"
"testing"
)

Expand All @@ -22,20 +23,22 @@ func TestFileGetter(t *testing.T) {
t.Fatalf("err: %s", err)
}

// Verify the destination folder is a symlink
fi, err := os.Lstat(dst)
if err != nil {
t.Fatalf("err: %s", err)
}
if fi.Mode()&os.ModeSymlink == 0 {
t.Fatal("destination is not a symlink")
}

// Verify the main file exists
mainPath := filepath.Join(dst, "main.tf")
if _, err := os.Stat(mainPath); err != nil {
t.Fatalf("err: %s", err)
}

// On Unix, verify it's a symlink; on Windows, just verify it works
if runtime.GOOS != "windows" {
fi, err := os.Lstat(dst)
if err != nil {
t.Fatalf("err: %s", err)
}
if fi.Mode()&os.ModeSymlink == 0 {
t.Fatal("destination is not a symlink")
}
}
}

func TestFileGetter_sourceFile(t *testing.T) {
Expand Down Expand Up @@ -116,17 +119,19 @@ func TestFileGetter_GetFile(t *testing.T) {
t.Fatalf("err: %s", err)
}

// Verify the destination folder is a symlink
fi, err := os.Lstat(dst)
if err != nil {
t.Fatalf("err: %s", err)
}
if fi.Mode()&os.ModeSymlink == 0 {
t.Fatal("destination is not a symlink")
}

// Verify the main file exists
assertContents(t, dst, "Hello\n")

// On Unix, verify it's a symlink; on Windows, just verify it works
if runtime.GOOS != "windows" {
fi, err := os.Lstat(dst)
if err != nil {
t.Fatalf("err: %s", err)
}
if fi.Mode()&os.ModeSymlink == 0 {
t.Fatal("destination is not a symlink")
}
}
}

func TestFileGetter_GetFile_Copy(t *testing.T) {
Expand Down
44 changes: 19 additions & 25 deletions get_http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"net/url"
"os"
"path/filepath"
"runtime"
"strconv"
"strings"
"testing"
Expand All @@ -32,7 +33,6 @@ func TestHttpGetter_header(t *testing.T) {

g := new(HttpGetter)
dst := filepath.Join(t.TempDir(), "target")
defer func() { _ = os.RemoveAll(dst) }()

var u url.URL
u.Scheme = "http"
Expand Down Expand Up @@ -79,7 +79,6 @@ func TestHttpGetter_requestHeader(t *testing.T) {
g.Header = make(http.Header)
g.Header.Add("X-Foobar", "foobar")
dst := filepath.Join(t.TempDir(), "target")
defer func() { _ = os.RemoveAll(dst) }()

var u url.URL
u.Scheme = "http"
Expand All @@ -105,7 +104,6 @@ func TestHttpGetter_meta(t *testing.T) {

g := new(HttpGetter)
dst := filepath.Join(t.TempDir(), "target")
defer func() { _ = os.RemoveAll(dst) }()

var u url.URL
u.Scheme = "http"
Expand Down Expand Up @@ -144,12 +142,16 @@ func TestHttpGetter_meta(t *testing.T) {
}

func TestHttpGetter_metaSubdir(t *testing.T) {
// Skip this test on Windows due to file:// URL subdirectory resolution issues
if runtime.GOOS == "windows" {
t.Skip("Skipping meta subdir test on Windows due to file:// URL path resolution issues")
}

ln := testHttpServer(t)
defer func() { _ = ln.Close() }()

g := new(HttpGetter)
dst := filepath.Join(t.TempDir(), "target")
defer func() { _ = os.RemoveAll(dst) }()
dst := filepath.Join(t.TempDir(), "nonexistent", "target")

var u url.URL
u.Scheme = "http"
Expand All @@ -169,12 +171,16 @@ func TestHttpGetter_metaSubdir(t *testing.T) {
}

func TestHttpGetter_metaSubdirGlob(t *testing.T) {
// Skip this test on Windows due to file:// URL subdirectory resolution issues
if runtime.GOOS == "windows" {
t.Skip("Skipping meta subdir glob test on Windows due to file:// URL path resolution issues")
}

ln := testHttpServer(t)
defer func() { _ = ln.Close() }()

g := new(HttpGetter)
dst := filepath.Join(t.TempDir(), "target")
defer func() { _ = os.RemoveAll(dst) }()
dst := filepath.Join(t.TempDir(), "nonexistent", "target")

var u url.URL
u.Scheme = "http"
Expand All @@ -199,7 +205,6 @@ func TestHttpGetter_none(t *testing.T) {

g := new(HttpGetter)
dst := filepath.Join(t.TempDir(), "target")
defer func() { _ = os.RemoveAll(dst) }()

var u url.URL
u.Scheme = "http"
Expand All @@ -225,7 +230,6 @@ func TestHttpGetter_resume(t *testing.T) {
defer func() { _ = ln.Close() }()

dst := filepath.Join(t.TempDir(), "target")
defer func() { _ = os.RemoveAll(dst) }()

dst = filepath.Join(dst, "..", "range")
f, err := os.Create(dst)
Expand Down Expand Up @@ -281,7 +285,6 @@ func TestHttpGetter_resumeNoRange(t *testing.T) {
defer func() { _ = ln.Close() }()

dst := filepath.Join(t.TempDir(), "target")
defer func() { _ = os.RemoveAll(dst) }()

dst = filepath.Join(dst, "..", "range")
f, err := os.Create(dst)
Expand Down Expand Up @@ -365,7 +368,6 @@ func TestHttpGetter_auth(t *testing.T) {

g := new(HttpGetter)
dst := filepath.Join(t.TempDir(), "target")
defer func() { _ = os.RemoveAll(dst) }()

var u url.URL
u.Scheme = "http"
Expand Down Expand Up @@ -404,7 +406,6 @@ func TestHttpGetter_authNetrc(t *testing.T) {

g := new(HttpGetter)
dst := filepath.Join(t.TempDir(), "target")
defer func() { _ = os.RemoveAll(dst) }()

var u url.URL
u.Scheme = "http"
Expand Down Expand Up @@ -467,7 +468,6 @@ func TestHttpGetter_cleanhttp(t *testing.T) {

g := new(HttpGetter)
dst := filepath.Join(t.TempDir(), "target")
defer func() { _ = os.RemoveAll(dst) }()

var u url.URL
u.Scheme = "http"
Expand Down Expand Up @@ -536,8 +536,7 @@ func TestHttpGetter__RespectsContextCanceled(t *testing.T) {
}

func TestHttpGetter__XTerraformGetLimit(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
ctx := t.Context()

ln := testHttpServerWithXTerraformGetLoop(t)

Expand All @@ -561,8 +560,7 @@ func TestHttpGetter__XTerraformGetLimit(t *testing.T) {
}

func TestHttpGetter__XTerraformGetDisabled(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
ctx := t.Context()

ln := testHttpServerWithXTerraformGetLoop(t)

Expand Down Expand Up @@ -596,8 +594,7 @@ func (testCustomDetector) Detect(src, _ string) (string, bool, error) {

// test a source url with no protocol
func TestHttpGetter__XTerraformGetDetected(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
ctx := t.Context()

ln := testHttpServerWithXTerraformGetDetected(t)

Expand Down Expand Up @@ -627,8 +624,7 @@ func TestHttpGetter__XTerraformGetDetected(t *testing.T) {
}

func TestHttpGetter__XTerraformGetProxyBypass(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
ctx := t.Context()

ln := testHttpServerWithXTerraformGetProxyBypass(t)

Expand Down Expand Up @@ -674,8 +670,7 @@ func TestHttpGetter__XTerraformGetProxyBypass(t *testing.T) {
}

func TestHttpGetter__XTerraformGetConfiguredGettersBypass(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
ctx := t.Context()

ln := testHttpServerWithXTerraformGetConfiguredGettersBypass(t)

Expand Down Expand Up @@ -720,8 +715,7 @@ func TestHttpGetter__XTerraformGetConfiguredGettersBypass(t *testing.T) {
}

func TestHttpGetter__endless_body(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
ctx := t.Context()

ln := testHttpServerWithEndlessBody(t)

Expand Down
Loading