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
8 changes: 4 additions & 4 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func run(cfg *Config) error {
baseBranch,
targetBranch,
appSelectionOptions,
cfg.Repo,
cfg.RepoSelector,
redirectRevisions,
)
if err != nil {
Expand Down Expand Up @@ -246,7 +246,7 @@ func run(cfg *Config) error {
targetApps,
baseBranch,
targetBranch,
cfg.Repo,
cfg.RepoSelector,
tempFolder,
redirectRevisions,
cfg.Debug,
Expand Down Expand Up @@ -330,7 +330,7 @@ func run(cfg *Config) error {
cfg.Concurrency,
baseApps.SelectedApps,
targetApps.SelectedApps,
cfg.Repo,
cfg.RepoSelector,
appSelectionOptions,
tempFolder,
)
Expand All @@ -343,7 +343,7 @@ func run(cfg *Config) error {
cfg.Concurrency,
baseApps.SelectedApps,
targetApps.SelectedApps,
cfg.Repo,
cfg.RepoSelector,
)
}
} else {
Expand Down
38 changes: 31 additions & 7 deletions cmd/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/dag-andersen/argocd-diff-preview/pkg/k3d"
"github.com/dag-andersen/argocd-diff-preview/pkg/kind"
"github.com/dag-andersen/argocd-diff-preview/pkg/minikube"
"github.com/dag-andersen/argocd-diff-preview/pkg/repository"
"github.com/dag-andersen/argocd-diff-preview/pkg/resource_filter"
"github.com/dag-andersen/argocd-diff-preview/pkg/vars"
)
Expand Down Expand Up @@ -97,6 +98,7 @@ type RawOptions struct {
BaseBranch string `mapstructure:"base-branch"`
TargetBranch string `mapstructure:"target-branch"`
Repo string `mapstructure:"repo"`
RepoRegex string `mapstructure:"repo-regex"`
OutputFolder string `mapstructure:"output-folder"`
SecretsFolder string `mapstructure:"secrets-folder"`
CreateCluster bool `mapstructure:"create-cluster"`
Expand Down Expand Up @@ -146,7 +148,7 @@ type Config struct {
LineCount uint
BaseBranch string
TargetBranch string
Repo string
RepoSelector repository.Selector
OutputFolder string
SecretsFolder string
CreateCluster bool
Expand Down Expand Up @@ -302,7 +304,8 @@ func Parse() *Config {
// Git related
rootCmd.Flags().StringP("base-branch", "b", DefaultBaseBranch, "Base branch name")
rootCmd.Flags().StringP("target-branch", "t", "", "Target branch name (required)")
rootCmd.Flags().String("repo", "", "Git Repository. Format: OWNER/REPO (required)")
rootCmd.Flags().String("repo", "", "Git repository. Format: OWNER/REPO. Mutually exclusive with --repo-regex")
rootCmd.Flags().String("repo-regex", "", "Regex matched against normalized Argo CD repoURL values for templated repository URLs. Mutually exclusive with --repo")

// Folders
rootCmd.Flags().StringP("output-folder", "o", DefaultOutputFolder, "Output folder where the diff will be saved")
Expand All @@ -327,7 +330,7 @@ func Parse() *Config {
rootCmd.Flags().Bool("auto-detect-files-changed", DefaultAutoDetectFilesChanged, "Auto detect files changed between branches")
rootCmd.Flags().Bool("ignore-invalid-watch-pattern", DefaultIgnoreInvalidWatchPattern, "Ignore invalid watch pattern Regex on Applications")
rootCmd.Flags().Bool("watch-if-no-watch-pattern-found", DefaultWatchIfNoWatchPatternFound, "Render applications without watch pattern")
rootCmd.Flags().String("redirect-target-revisions", "", "List of target revisions to redirect")
rootCmd.Flags().String("redirect-target-revisions", "", "Comma-separated source targetRevision values to redirect to the target branch. Example: main,HEAD. By default, every targetRevision in matching repositories is redirected")
rootCmd.Flags().String("title", DefaultTitle, "Custom title for the markdown output")
rootCmd.Flags().Bool("hide-deleted-app-diff", DefaultHideDeletedAppDiff, "Hide diff content for fully deleted applications (only show deletion header)")
rootCmd.Flags().String("argocd-ui-url", DefaultArgocdUIURL, "Argo CD URL to generate application links in diff output (e.g., https://argocd.example.com)")
Expand Down Expand Up @@ -373,8 +376,11 @@ func (o *RawOptions) checkRequired() []string {
if o.TargetBranch == "" {
errors = append(errors, "target-branch")
}
if o.Repo == "" {
errors = append(errors, "repo")
if o.Repo == "" && o.RepoRegex == "" {
errors = append(errors, "repo or repo-regex")
}
if o.Repo != "" && o.RepoRegex != "" {
errors = append(errors, "repo and repo-regex are mutually exclusive")
}
return errors
}
Expand All @@ -390,7 +396,6 @@ func (o *RawOptions) ToConfig() (*Config, error) {
LineCount: o.LineCount,
BaseBranch: o.BaseBranch,
TargetBranch: o.TargetBranch,
Repo: o.Repo,
OutputFolder: o.OutputFolder,
SecretsFolder: o.SecretsFolder,
CreateCluster: o.CreateCluster,
Expand Down Expand Up @@ -447,6 +452,11 @@ func (o *RawOptions) ToConfig() (*Config, error) {
return nil, fmt.Errorf("invalid file-regex: %w", err)
}

cfg.RepoSelector, err = o.parseRepositorySelector()
if err != nil {
return nil, err
}

// Parse selectors
cfg.Selectors, err = o.parseSelectors()
if err != nil {
Expand Down Expand Up @@ -521,6 +531,15 @@ func (o *RawOptions) parseFileRegex() (*regexp.Regexp, error) {
return regexp.Compile(o.FileRegex)
}

// parseRepositorySelector returns a Repository Selector based on the repo or repo-regex flags
func (o *RawOptions) parseRepositorySelector() (repository.Selector, error) {
repoSelector, err := repository.NewSelector(o.Repo, o.RepoRegex)
if err != nil {
return repository.Selector{}, fmt.Errorf("invalid repo-regex: %w", err)
}
Comment on lines +535 to +539
return *repoSelector, nil
}

// parseRedirectRevisions parses the redirect-target-revisions string into a slice of strings
func (o *RawOptions) parseRedirectRevisions() []string {
if o.RedirectTargetRevisions == "" {
Expand Down Expand Up @@ -654,7 +673,12 @@ func (o *Config) LogConfig() {
if o.ArgocdConfigPath != DefaultArgocdConfigPath {
log.Info().Msgf("✨ - argocd-config-dir: %s", o.ArgocdConfigPath)
}
log.Info().Msgf("✨ - repo: %s", o.Repo)
if o.RepoSelector.Repo != "" {
log.Info().Msgf("✨ - repo: %s", o.RepoSelector.Repo)
}
if o.RepoSelector.Regex != nil {
log.Info().Msgf("✨ - repo-regex: %s", o.RepoSelector.Regex.String())
}
log.Info().Msgf("✨ - timeout: %d seconds", o.Timeout)
if o.LogFormat != DefaultLogFormat {
log.Info().Msgf("✨ - log-format: %s", o.LogFormat)
Expand Down
7 changes: 4 additions & 3 deletions docs/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ This document describes all the available options for `argocd-diff-preview`. Opt
## Usage

```bash
argocd-diff-preview [FLAGS] [OPTIONS] --repo <repo> --target-branch <target-branch>
argocd-diff-preview [FLAGS] [OPTIONS] (--repo <repo> | --repo-regex <regex>) --target-branch <target-branch>
```

## Required Options

| Flag | Environment Variable | Description |
| --------------------------------------- | -------------------- | -------------------------------------------------------------------------------- |
| `--repo <repo>` | `REPO` | Git Repository in format `OWNER/REPO` (e.g., `dag-andersen/argocd-diff-preview`) |
| `--repo <repo>` or `--repo-regex <regex>` | `REPO` or `REPO_REGEX` | Git repository in format `OWNER/REPO`, or a regex for templated Argo CD repoURL values. These options are mutually exclusive |
| `--target-branch <target-branch>`, `-t` | `TARGET_BRANCH` | Target branch name (the branch you want to compare with the base branch) |

## Flags
Expand Down Expand Up @@ -63,8 +63,9 @@ argocd-diff-preview [FLAGS] [OPTIONS] --repo <repo> --target-branch <target-bran
| `--log-format <format>` | `LOG_FORMAT` | `human` | Log format. Options: `human`, `json` |
| `--max-diff-length <length>` | `MAX_DIFF_LENGTH` | `65536` | Max diff message character count (only limits the generated Markdown file) |
| `--output-folder <folder>`, `-o` | `OUTPUT_FOLDER` | `./output` | Output folder where the diff will be saved |
| `--redirect-target-revisions <revs>` | `REDIRECT_TARGET_REVISIONS` | - | List of target revisions to redirect |
| `--redirect-target-revisions <revs>` | `REDIRECT_TARGET_REVISIONS` | - | Comma-separated source targetRevision values to redirect to the target branch. Example: main,HEAD. By default, every targetRevision in matching repositories is redirected |
| `--render-method <method>` | `RENDER_METHOD` | `server-api` | Manifest rendering method. Options: `cli`, `server-api`, `repo-server-api` |
| `--repo-regex <regex>` | `REPO_REGEX` | - | Advanced repository matcher for templated Argo CD repoURL values. Mutually exclusive with `--repo` |
| `--secrets-folder <folder>`, `-s` | `SECRETS_FOLDER` | `./secrets` | Secrets folder where the secrets are read from |
| `--selector <selector>`, `-l` | `SELECTOR` | - | Label selector to filter on (e.g., `key1=value1,key2=value2`) |
| `--timeout <seconds>` | `TIMEOUT` | `180` | Set timeout in seconds |
Expand Down
15 changes: 13 additions & 2 deletions integration-test/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ type TestCase struct {
ArgocdConfigDir string // Custom argocd-config directory (relative to integration-test/); overrides auto-derived path
ArgocdUIURL string // Argo CD URL for generating application links in diff output
TraverseAppOfApps string // If "true", enables recursive child app discovery (--traverse-app-of-apps)
RepoRegex string // If set, use --repo-regex instead of --repo
ExpectFailure bool // If true, the test is expected to fail
}

Expand Down Expand Up @@ -234,6 +235,7 @@ var testCases = []TestCase{
BaseBranch: "integration-test/branch-9/base",
Suffix: "-3",
MaxDiffLength: "400",
RepoRegex: "go.*diff-pre",
},
{
Name: "branch-10/target-1",
Expand Down Expand Up @@ -272,6 +274,7 @@ var testCases = []TestCase{
TargetBranch: "integration-test/branch-13/target",
BaseBranch: "integration-test/branch-13/base",
Suffix: "-1",
RepoRegex: "-diff-",
},
{
Name: "branch-13/target-2",
Expand Down Expand Up @@ -872,7 +875,11 @@ func runWithDocker(tc TestCase, createCluster bool, runDirs RunDirs) error {
// Add environment variables
args = append(args, "-e", fmt.Sprintf("BASE_BRANCH=%s", tc.BaseBranch))
args = append(args, "-e", fmt.Sprintf("TARGET_BRANCH=%s", tc.TargetBranch))
args = append(args, "-e", fmt.Sprintf("REPO=%s/%s", defaultGitHubOrg, defaultGitOpsRepo))
if tc.RepoRegex != "" {
args = append(args, "-e", fmt.Sprintf("REPO_REGEX=%s", tc.RepoRegex))
} else {
args = append(args, "-e", fmt.Sprintf("REPO=%s/%s", defaultGitHubOrg, defaultGitOpsRepo))
}
args = append(args, "-e", fmt.Sprintf("TIMEOUT=%s", defaultTimeout))
args = append(args, "-e", fmt.Sprintf("LINE_COUNT=%s", getLineCount(tc)))
args = append(args, "-e", fmt.Sprintf("MAX_DIFF_LENGTH=%s", getMaxDiffLength(tc)))
Expand Down Expand Up @@ -964,7 +971,6 @@ func buildArgs(tc TestCase, createCluster bool, runDirs RunDirs, repoRoot string
args := []string{
"--base-branch", tc.BaseBranch,
"--target-branch", tc.TargetBranch,
"--repo", fmt.Sprintf("%s/%s", defaultGitHubOrg, defaultGitOpsRepo),
"--argocd-namespace", argocdNamespace,
"--timeout", defaultTimeout,
"--line-count", getLineCount(tc),
Expand All @@ -973,6 +979,11 @@ func buildArgs(tc TestCase, createCluster bool, runDirs RunDirs, repoRoot string
"--keep-cluster-alive",
"--disable-client-throttling",
}
if tc.RepoRegex != "" {
args = append(args, "--repo-regex", tc.RepoRegex)
} else {
args = append(args, "--repo", fmt.Sprintf("%s/%s", defaultGitHubOrg, defaultGitOpsRepo))
}

// Don't keep cluster alive for tests that expect failure (cluster may be in broken state)
if !tc.ExpectFailure {
Expand Down
3 changes: 2 additions & 1 deletion pkg/argoapplication/app_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ package argoapplication
import (
"errors"
"fmt"
"strings"

"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
"github.com/dag-andersen/argocd-diff-preview/pkg/argocd"
)

func isErrorCondition(condType string) bool {
return condType != "" && containsIgnoreCase(condType, "error")
return condType != "" && strings.Contains(strings.ToLower(condType), "error")
}

// GetApplicationStatus returns the error status of an application
Expand Down
11 changes: 6 additions & 5 deletions pkg/argoapplication/application_sets.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/dag-andersen/argocd-diff-preview/pkg/argocd"
"github.com/dag-andersen/argocd-diff-preview/pkg/git"
"github.com/dag-andersen/argocd-diff-preview/pkg/repository"
"github.com/dag-andersen/argocd-diff-preview/pkg/utils"
)

Expand All @@ -20,7 +21,7 @@ func ConvertAppSetsToAppsInBothBranches(
targetApps *ArgoSelection,
baseBranch *git.Branch,
targetBranch *git.Branch,
repo string,
repoSelector repository.Selector,
tempFolder string,
redirectRevisions []string,
debug bool,
Expand All @@ -40,7 +41,7 @@ func ConvertAppSetsToAppsInBothBranches(
debug,
failOnDuplicateGeneratedApplications,
appSelectionOptions,
repo,
repoSelector,
redirectRevisions,
)

Expand All @@ -58,7 +59,7 @@ func ConvertAppSetsToAppsInBothBranches(
debug,
failOnDuplicateGeneratedApplications,
appSelectionOptions,
repo,
repoSelector,
redirectRevisions,
)
if err != nil {
Expand All @@ -79,7 +80,7 @@ func processAppSets(
debug bool,
failOnDuplicateGeneratedApplications bool,
appSelectionOptions ApplicationSelectionOptions,
repo string,
repoSelector repository.Selector,
redirectRevisions []string,
) (*ArgoSelection, error) {

Expand Down Expand Up @@ -150,7 +151,7 @@ func processAppSets(
argocd.Namespace,
selection.SelectedApps,
branch,
repo,
repoSelector,
redirectRevisions,
)
if err != nil {
Expand Down
11 changes: 6 additions & 5 deletions pkg/argoapplication/applications.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/dag-andersen/argocd-diff-preview/pkg/fileparsing"
"github.com/dag-andersen/argocd-diff-preview/pkg/git"
"github.com/dag-andersen/argocd-diff-preview/pkg/repository"
"github.com/dag-andersen/argocd-diff-preview/pkg/utils"
"sigs.k8s.io/yaml"
)
Expand Down Expand Up @@ -74,14 +75,14 @@ func GetApplicationsForBranches(
baseBranch *git.Branch,
targetBranch *git.Branch,
appSelectionOptions ApplicationSelectionOptions,
repo string,
repoSelector repository.Selector,
redirectRevisions []string,
) (*ArgoSelection, *ArgoSelection, error) {
baseApps, err := getApplications(
argocdNamespace,
baseBranch,
appSelectionOptions,
repo,
repoSelector,
redirectRevisions,
)
if err != nil {
Expand All @@ -92,7 +93,7 @@ func GetApplicationsForBranches(
argocdNamespace,
targetBranch,
appSelectionOptions,
repo,
repoSelector,
redirectRevisions,
)
if err != nil {
Expand All @@ -107,7 +108,7 @@ func getApplications(
argocdNamespace string,
branch *git.Branch,
appSelectionOptions ApplicationSelectionOptions,
repo string,
repoSelector repository.Selector,
redirectRevisions []string,
) (*ArgoSelection, error) {
log.Info().Str("branch", branch.Name).Msg("🤖 Fetching all files for branch")
Expand Down Expand Up @@ -156,7 +157,7 @@ func getApplications(
argocdNamespace,
selection.SelectedApps,
branch,
repo,
repoSelector,
redirectRevisions,
)
if err != nil {
Expand Down
Loading
Loading