From 8c7134e8ce8bec8bcf51509889cc3d8286439a68 Mon Sep 17 00:00:00 2001 From: aknysh Date: Thu, 15 Dec 2022 11:24:59 -0500 Subject: [PATCH] Add `atmos describe affected` command --- internal/exec/describe_affected.go | 28 +++--- .../commands/describe/describe-affected.md | 91 ++++++++++++++++--- 2 files changed, 91 insertions(+), 28 deletions(-) diff --git a/internal/exec/describe_affected.go b/internal/exec/describe_affected.go index 0ccfe5454..9f04fe689 100644 --- a/internal/exec/describe_affected.go +++ b/internal/exec/describe_affected.go @@ -156,9 +156,9 @@ func ExecuteDescribeAffected( // If `ref` flag is not provided, it will clone the HEAD of the default branch if ref != "" { cloneOptions.ReferenceName = plumbing.ReferenceName(ref) - u.PrintInfoVerbose(verbose, fmt.Sprintf("\nChecking out Git ref: %s\n", ref)) + u.PrintInfoVerbose(verbose, fmt.Sprintf("\nChecking out Git ref '%s' ...\n", ref)) } else { - u.PrintInfoVerbose(verbose, "\nChecking out the HEAD of the default branch\n") + u.PrintInfoVerbose(verbose, "\nChecking out the HEAD of the default branch ...\n") } if verbose { @@ -176,14 +176,14 @@ func ExecuteDescribeAffected( } if ref != "" { - u.PrintInfoVerbose(verbose, fmt.Sprintf("\nChecked out Git ref: %s\n", ref)) + u.PrintInfoVerbose(verbose, fmt.Sprintf("\nChecked out Git ref '%s'\n", ref)) } else { - u.PrintInfoVerbose(verbose, fmt.Sprintf("\nChecked out Git ref: %s\n", remoteRepoHead.Name())) + u.PrintInfoVerbose(verbose, fmt.Sprintf("\nChecked out Git ref '%s'\n", remoteRepoHead.Name())) } // Check if a commit SHA was provided and checkout the repo at that commit SHA if sha != "" { - u.PrintInfoVerbose(verbose, fmt.Sprintf("\nChecking out commit SHA: %s\n", sha)) + u.PrintInfoVerbose(verbose, fmt.Sprintf("\nChecking out commit SHA '%s' ...\n", sha)) w, err := remoteRepo.Worktree() if err != nil { @@ -202,7 +202,7 @@ func ExecuteDescribeAffected( return nil, err } - u.PrintInfoVerbose(verbose, fmt.Sprintf("\nChecked out commit SHA: %s\n", sha)) + u.PrintInfoVerbose(verbose, fmt.Sprintf("\nChecked out commit SHA '%s'\n", sha)) } currentStacks, err := ExecuteDescribeStacks(cliConfig, "", nil, nil, nil) @@ -229,26 +229,26 @@ func ExecuteDescribeAffected( } if verbose { - u.PrintInfo(fmt.Sprintf("Local repo HEAD: %s", localRepoHead)) + u.PrintInfo(fmt.Sprintf("Current working repo HEAD: %s", localRepoHead)) u.PrintInfo(fmt.Sprintf("Remote repo HEAD: %s", remoteRepoHead)) } - u.PrintInfoVerbose(verbose, fmt.Sprintf("\nGetting local repo commit object...")) + u.PrintInfoVerbose(verbose, fmt.Sprintf("\nGetting current working repo commit object...")) localCommit, err := localRepo.CommitObject(localRepoHead.Hash()) if err != nil { return nil, err } - u.PrintInfoVerbose(verbose, fmt.Sprintf("Got local repo commit object")) - u.PrintInfoVerbose(verbose, fmt.Sprintf("Getting local repo commit tree...")) + u.PrintInfoVerbose(verbose, fmt.Sprintf("Got current working repo commit object")) + u.PrintInfoVerbose(verbose, fmt.Sprintf("Getting current working repo commit tree...")) localTree, err := localCommit.Tree() if err != nil { return nil, err } - u.PrintInfoVerbose(verbose, fmt.Sprintf("Got local repo commit tree")) + u.PrintInfoVerbose(verbose, fmt.Sprintf("Got current working repo commit tree")) u.PrintInfoVerbose(verbose, fmt.Sprintf("Getting remote repo commit object...")) remoteCommit, err := remoteRepo.CommitObject(remoteRepoHead.Hash()) @@ -265,15 +265,15 @@ func ExecuteDescribeAffected( } u.PrintInfoVerbose(verbose, fmt.Sprintf("Got remote repo commit tree")) - u.PrintInfoVerbose(verbose, fmt.Sprintf("Finding diff between the local and remote commits...")) + u.PrintInfoVerbose(verbose, fmt.Sprintf("Finding diff between the current working branch and remote branch ...")) - // Find a slice of Patch objects with all the changes between the local and remote trees + // Find a slice of Patch objects with all the changes between the current working and remote trees patch, err := localTree.Patch(remoteTree) if err != nil { return nil, err } - u.PrintInfoVerbose(verbose, fmt.Sprintf("Found diff between the local and remote commits")) + u.PrintInfoVerbose(verbose, fmt.Sprintf("Found diff between the current working branch and remote branch")) u.PrintInfoVerbose(verbose, "\nChanged files:") var changedFiles []string diff --git a/website/docs/cli/commands/describe/describe-affected.md b/website/docs/cli/commands/describe/describe-affected.md index fa48b231d..68d8acd34 100644 --- a/website/docs/cli/commands/describe/describe-affected.md +++ b/website/docs/cli/commands/describe/describe-affected.md @@ -10,15 +10,78 @@ description: This command produces a list of the affected Atmos components and s Use this command to show a list of the affected Atmos components and stacks given two Git commits. ::: +## Description + +The command uses two different Git commits to produce a list of affected Atmos components and stacks. + +For the first commit, the command assumes that the current repo root is a Git checkout. An error will be thrown if the current repo is not a Git +repository (`.git` folder does not exist or is configured incorrectly). + +The second commit is specified on the command line by using +the `--ref` ([Git References](https://git-scm.com/book/en/v2/Git-Internals-Git-References)) or `--sha` (commit SHA) flags. + +Either `--ref` or `--sha` should be used. If both flags are provided at the same time, the command will first clone the remote branch pointed to by +the `--ref` flag and then checkout the Git commit pointed to by the `--sha` flag (`--sha` flag overrides `--ref` flag). + +If the flags are not provided, the `ref` will be set automatically to the reference to the default branch (e.g. `main`) and the commit SHA will point +to the `HEAD` of the branch. + +The command works by: + +- Cloning the branch (`--ref`) or checking out the commit (`--sha`) of the remote target branch +- Deep merging all stack configurations for both the current working branch and the target branch +- Looking for changes in the component directories +- Comparing each section of the stack configuration looking for differences +- Output a JSON or YAML document consisting of a list of affected components and stacks and what caused it to be affected +
-:::info -For the first commit, the command assumes that the repo root is a Git checkout. +```shell +> atmos describe affected --verbose=true -The second commit is specified on the command line by using the `--ref` (Git Reference) or `--sha` (commit SHA) flags. +Cloning repo 'https://github.com/cloudposse/atmos' into the temp dir '/var/folders/g5/lbvzy_ld2hx4mgrgyp19bvb00000gn/T/16710736261366892599' -If the flags are not provided, the `ref` will be the default branch (e.g. `main`) and the commit SHA will point to the `HEAD` of the branch. -::: +Checking out the HEAD of the default branch ... + +Enumerating objects: 4215, done. +Counting objects: 100% (1157/1157), done. +Compressing objects: 100% (576/576), done. +Total 4215 (delta 658), reused 911 (delta 511), pack-reused 3058 + +Checked out Git ref 'refs/heads/master' + +Current working repo HEAD: 7d37c1e890514479fae404d13841a2754be70cbf refs/heads/describe-affected +Remote repo HEAD: 40210e8d365d3d88ac13c0778c0867b679bbba69 refs/heads/master + +Changed files: + +examples/complete/components/terraform/infra/vpc/main.tf +internal/exec/describe_affected.go +website/docs/cli/commands/describe/describe-affected.md + +Affected components and stacks: + +[ + { + "stack": "tenant1-ue2-dev", + "component_type": "terraform", + "component": "infra/vpc", + "affected": "component" + }, + { + "stack": "tenant1-ue2-prod", + "component_type": "terraform", + "component": "infra/vpc", + "affected": "component" + }, + { + "stack": "tenant1-ue2-staging", + "component_type": "terraform", + "component": "infra/vpc", + "affected": "component" + } +] +``` ## Usage @@ -47,17 +110,17 @@ atmos describe affected --sha 3a5eafeab90426bd82bf5899896b28cc0bab3073 ## Flags -| Flag | Description | Required | -|:------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------|:---------| -| `--ref` | Git reference with which to compare the current branch. Refer to [Git References](https://git-scm.com/book/en/v2/Git-Internals-Git-References) for more details | no | -| `--sha` | Git commit SHA with which to compare the current branch | no | -| `--file` | If specified, write the result to the file | no | -| `--format` | Specify the output format: `json` or `yaml` (`json` is default) | no | -| `--verbose` | Print more detailed output when cloning and checking out the Git repository | no | +| Flag | Description | Required | +|:------------|:------------------------------------------------------------------------------------------------------------------------------|:---------| +| `--ref` | [Git Reference](https://git-scm.com/book/en/v2/Git-Internals-Git-References) with which to compare the current working branch | no | +| `--sha` | Git commit SHA with which to compare the current working branch | no | +| `--file` | If specified, write the result to the file | no | +| `--format` | Specify the output format: `json` or `yaml` (`json` is default) | no | +| `--verbose` | Print more detailed output when cloning and checking out the Git repository and processing the result | no | ## Output -The command outputs a list of objects (in JSON or YAML formats). +The command outputs a list of objects (in JSON or YAML format). Each object has the following schema: @@ -81,7 +144,7 @@ where: - `stack.env` - the `env` component section in the stack config has been modified - `stack.settings` - the `settings` component section in the stack config has been modified - `stack.metadata` - the `metadata` component section in the stack config has been modified - - `component` - the Terraform or Helmfile component (Terraform/Helmfile files) that the affected Atmos component provisions has been changed + - `component` - the Terraform or Helmfile component that the Atmos component provisions has been changed