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
18 changes: 8 additions & 10 deletions integration-test/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,14 @@ This directory contains integration tests for `argocd-diff-preview`. These tests
### Quick Reference

```bash
# Build and run all integration tests with Go binary (CLI mode)
# Build and run all integration tests with Go binary using the default render method
make run-integration-tests-go

# Build and run all integration tests with Docker
# Build and run all integration tests with Docker using the default render method
make run-integration-tests-docker

# Run with Argo CD server API mode
make run-integration-tests-go-with-api
make run-integration-tests-docker-with-api
# Run with Argo CD CLI mode
make run-integration-tests-go-with-cli

# Run with Argo CD repo server API mode (experimental)
make run-integration-tests-go-with-repo-server-api
Expand All @@ -35,14 +34,13 @@ make check-release

| Make Target | Description |
| ---------------------------------------------- | --------------------------------------------------------------------------------------------- |
| `run-integration-tests-go` | Builds Go binary, runs all tests in CLI mode |
| `run-integration-tests-docker` | Builds Docker image, runs all tests using Docker |
| `run-integration-tests-go-with-api` | Runs all tests forcing `--render-method=server-api` |
| `run-integration-tests-docker-with-api` | Runs all tests with Docker + `--render-method=server-api` |
| `run-integration-tests-go` | Builds Go binary, runs all tests using the default render method |
| `run-integration-tests-docker` | Builds Docker image, runs all tests using Docker and the default render method |
| `run-integration-tests-go-with-cli` | Runs all tests forcing `--render-method=cli` |
| `run-integration-tests-go-with-repo-server-api`| Runs all tests forcing `--render-method=repo-server-api` |
| `run-integration-tests-docker-with-repo-server-api` | Runs all tests with Docker + `--render-method=repo-server-api` |
| `update-integration-tests` | Regenerates expected output files (use after intentional changes) |
| `check-release` | Full pre-release validation: lint → unit tests → Go (CLI) → Go (repo-server-api) → Docker (server-api) |
| `check-release` | Full pre-release validation: lint → unit tests → Go (repo-server-api) → Go (CLI) → Docker default |
| `check-release-repeat` | Runs `check-release` in a loop until failure (for catching flaky tests) |

### Running a Single Test
Expand Down
22 changes: 10 additions & 12 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -100,26 +100,23 @@ run-unit-tests:
# go test -coverprofile=coverage.out ./...
# go tool cover -html=coverage.out

# New Go-based integration tests
# Go-based integration tests. The default targets use the tool default render method.
run-integration-tests-go: go-build
cd integration-test && go test -v -timeout 60m -run TestIntegration ./...

run-integration-tests-docker: go-build
cd integration-test && go test -v -timeout 60m -run TestIntegration -docker ./...

# Run integration tests with the Argo CD server API
run-integration-tests-go-with-api: go-build
cd integration-test && go test -v -timeout 60m -run TestIntegration -render-method=server-api ./...

run-integration-tests-docker-with-api: go-build
cd integration-test && go test -v -timeout 60m -run TestIntegration -docker -render-method=server-api ./...
# Run integration tests with the Argo CD CLI renderer
run-integration-tests-go-with-cli: go-build
cd integration-test && go test -v -timeout 60m -run TestIntegration -render-method=cli ./...

# Run integration tests with the Argo CD repo server API
run-integration-tests-go-with-repo-server-api: go-build
cd integration-test && go test -v -timeout 60m -run TestIntegration -render-method=repo-server-api ./...

run-integration-tests-docker-with-repo-server-api: go-build
cd integration-test && go test -v -timeout 60m -run TestIntegration -docker -render-method=repo-server-api ./...
cd integration-test && go test -v -timeout 60m -run TestIntegration -render-method=repo-server-api -docker ./...

# Update golden files for integration tests
update-integration-tests: go-build
Expand All @@ -130,15 +127,16 @@ update-integration-tests-docker: go-build

# Run before release
check-release: run-lint run-unit-tests
$(MAKE) run-integration-tests-go
$(MAKE) run-integration-tests-go-with-repo-server-api
$(MAKE) run-integration-tests-docker-with-api
$(MAKE) run-integration-tests-go-with-cli
$(MAKE) run-integration-tests-docker

# Loop the above commands until one fails
check-release-repeat:
@i=1; while true; do \
echo "⭐⭐⭐⭐⭐ Iteration $$i ⭐⭐⭐⭐⭐"; \
$(MAKE) run-integration-tests-go || exit 1; \
$(MAKE) run-integration-tests-docker-with-api || exit 1; \
$(MAKE) run-integration-tests-go-with-repo-server-api || exit 1; \
$(MAKE) run-integration-tests-go-with-cli || exit 1; \
$(MAKE) run-integration-tests-docker || exit 1; \
i=$$((i + 1)); \
done
57 changes: 49 additions & 8 deletions pkg/reposerverextract/extract.go
Original file line number Diff line number Diff line change
Expand Up @@ -565,20 +565,22 @@ func buildManifestRequestForSource(
}
}

// ── Fast path: no ref sources → stream the whole branch folder ────────────
// The repo server resolves ApplicationSource.Path relative to the stream
// root (workDir), so streaming the entire branch folder and setting Path
// correctly is sufficient. This also handles kustomize overlays that
// reference sibling directories (e.g. ../../base) which would be missing
// if we only copied the leaf path into a temp dir.
// Fast path: no ref sources.
// The repo server resolves ApplicationSource.Path relative to the stream root
// (workDir). For local Helm charts, stream the chart directory as the workDir
// root and clear Path in the request. This avoids sending unrelated monorepo
// files to the repo server, which can otherwise fail Argo CD's symlink safety
// checks before rendering even starts. If a path also contains a kustomization
// file, keep the branch root because Argo CD discovers it as Kustomize even
// when Chart.yaml exists for kustomize helmCharts support.
//
// Special case: if the primary source has a Chart field (external Helm
// registry chart) there are no local files to stream. We signal this by
// returning an empty streamDir; the caller will use the regular
// (non-file-streaming) GenerateManifest RPC instead.
if len(refSources) == 0 {
if primarySource.Chart != "" {
// Remote Helm chart no local files to stream.
// Remote Helm chart - no local files to stream.
return newManifestRequest(&primarySource), "", nil, nil
}
// Cross-repo source: the source's repoURL points at a different
Expand All @@ -593,7 +595,15 @@ func buildManifestRequestForSource(
Msg("Source repoURL does not match PR repo - using remote RPC")
return newManifestRequest(&primarySource), "", nil, nil
}
return newManifestRequest(&primarySource), branchFolder, nil, nil
streamDir, cleanup, err := buildStreamDirForLocalSource(branchFolder, primarySource)
if err != nil {
return nil, "", nil, err
}
requestSource := primarySource
if streamDir != branchFolder {
requestSource.Path = ""
}
return newManifestRequest(&requestSource), streamDir, cleanup, nil
}
// Slow path: ref sources present
//
Expand Down Expand Up @@ -707,6 +717,37 @@ func buildManifestRequestForSource(
return request, tempDir, cleanup, nil
}

func buildStreamDirForLocalSource(branchFolder string, source v1alpha1.ApplicationSource) (streamDir string, cleanup func(), err error) {
if source.Path == "" {
return branchFolder, nil, nil
}

sourceDir := filepath.Join(branchFolder, source.Path)
if _, err := os.Stat(sourceDir); err != nil {
return "", nil, fmt.Errorf("failed to inspect source dir %q: %w", sourceDir, err)
}
if isLocalHelmChart(sourceDir) && !isKustomizeSource(sourceDir) {
return sourceDir, nil, nil
}

return branchFolder, nil, nil
}

func isLocalHelmChart(sourceDir string) bool {
info, err := os.Stat(filepath.Join(sourceDir, "Chart.yaml"))
return err == nil && !info.IsDir()
}

func isKustomizeSource(sourceDir string) bool {
for _, filename := range []string{"kustomization.yaml", "kustomization.yml", "Kustomization"} {
info, err := os.Stat(filepath.Join(sourceDir, filename))
if err == nil && !info.IsDir() {
return true
}
}
return false
}

// splitRefPath splits a $refName/path/to/file value-file string into
// (refName, path/to/file, true), or returns ("", "", false) if the string
// doesn't match the expected pattern. A ref with no sub-path (e.g. "$cfg"
Expand Down
Loading
Loading