8000 Add pager to atmos describe affected command by samtholiya · Pull Request #1236 · cloudposse/atmos · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Add pager to atmos describe affected command #1236

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 32 commits into
base: feature/dev-3162-add-pager-to-atmos-describe-component-command
Choose a base branch
from

Conversation

samtholiya
Copy link
Collaborator
@samtholiya samtholiya commented May 4, 2025

what

  • Updated describe affected with pager

image

why

  • Makes easier for users to view the content

references

Summary by CodeRabbit

  • New Features
    • Introduced an interactive terminal pager with scrolling, clipboard support, and syntax highlighting for command outputs.
    • Added a --pager flag to CLI commands to enable or disable paged output.
    • Enhanced terminal paging configuration with environment variable support and customizable pager settings.
  • Bug Fixes
    • Improved output formatting and paging reliability for large or complex command outputs.
  • Documentation
    • Updated CLI documentation to include the --pager flag usage and examples.
  • Tests
      Added extensive tests covering pager behavior, configuration parsing, output formatting, and CLI command execution.
  • Style/Refactor
    • Refactored command execution and output handling to modularize paging, formatting, and argument parsing for better maintainability.

@samtholiya samtholiya added minor New features that do not break anything and removed size/xl labels May 4, 2025
Copy link
mergify bot commented May 4, 2025

Important

Cloud Posse Engineering Team Review Required

This pull request modifies files that require Cloud Posse's review. Please be patient, and a core maintainer will review your changes.

To expedite this process, reach out to us on Slack in the #pr-reviews channel.

@mergify mergify bot added the needs-cloudposse Needs Cloud Posse assistance label May 4, 2025
Copy link
mergify bot commented May 4, 2025

Warning

This PR exceeds the recommended limit of 1,000 lines.

Large PRs are difficult to review and may be rejected due to their size.

Please verify that this PR does not address multiple issues.
Consider refactoring it into smaller, more focused PRs to facilitate a smoother review process.

Copy link
codecov bot commented May 4, 2025

Codecov Report

Attention: Patch coverage is 49.18415% with 654 lines in your changes missing coverage. Please review.

Project coverage is 48.38%. Comparing base (c87cd51) to head (70871f0).
Report is 80 commits behind head on feature/dev-3162-add-pager-to-atmos-describe-component-command.

Files with missing lines Patch % Lines
internal/exec/docs_generate.go 41.15% 112 Missing and 21 partials ⚠️
pkg/pager/model.go 50.94% 103 Missing and 1 partial ⚠️
cmd/describe_affected.go 0.00% 79 Missing ⚠️
internal/exec/template_utils.go 52.38% 34 Missing and 16 partials ⚠️
internal/exec/describe_affected.go 54.83% 38 Missing and 4 partials ⚠️
internal/exec/terraform_outputs.go 59.77% 35 Missing ⚠️
pkg/utils/highlight_utils.go 7.89% 35 Missing ⚠️
internal/exec/terraform.go 45.65% 25 Missing ⚠️
cmd/describe_config.go 0.00% 23 Missing ⚠️
internal/exec/file_utils.go 30.00% 17 Missing and 4 partials ⚠️
... and 16 more
Additional details and impacted files
@@                                         Coverage Diff                                         @@
##           feature/dev-3162-add-pager-to-atmos-describe-component-command    #1236       +/-   ##
===================================================================================================
+ Coverage                                                           32.89%   48.38%   +15.48%     
===================================================================================================
  Files                                                                 223      229        +6     
  Lines                                                               23791    24602      +811     
===================================================================================================
+ Hits                                                                 7827    11904     +4077     
+ Misses                                                              14798    11111     -3687     
- Partials                                                             1166     1587      +421     
Flag Coverage Δ
unittests 48.38% <49.18%> (+15.48%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@samtholiya samtholiya changed the title Feature/dev 3182 add pager to atmos describe affected command Add pager to atmos describe affected command May 5, 2025
…#1235)

* updates

* updates

* updates

* updates

* updates

* updates

* updates

* updates

* updates

* updates

* updates

* updates

* updates

* updates

* updates

* updates

* updates

* [autofix.ci] apply automated fixes

* updates

* updates

* updates

* updates

* updates

* updates

* updates

* updates

* Apply suggestions from code review

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <erik@cloudposse.com>

* updates

* updates

* updates

* Apply suggestions from code review

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <erik@cloudposse.com>

* updates

* [autofix.ci] apply automated fixes

* updates

---------

Co-authored-by: autofix-ci[bot] <11482
8000
7586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <erik@cloudposse.com>
Copy link
mergify bot commented May 7, 2025

💥 This pull request now has conflicts. Could you fix it @samtholiya? 🙏

@mergify mergify bot added the conflict This PR has conflicts label May 7, 2025
Benbentwo and others added 5 commits May 7, 2025 10:42
* docs generate

* readme buildout using Gomplate 3.x with teml.Exec issue fixed

* readme generationggomplate 3.11.8 work,s no terrafor yet

* fix for windwos gomplate

* gomodtidy

* dependant acceptnace tests fix + draft test cases

* Update internal/exec/docs_generate.go

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <erik@cloudposse.com>

* use go-getter to download files

* atmos.yaml

* Update cmd/docs_generate.go

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <erik@cloudposse.com>

* examples back

* terrafrom test/mergo

* moving fixtures to tests and reverting back the comments in template utils

* test cases

* initial version of documentation

* mdx fixes

* mdx layout fix

* typo fix

* defer removeTempDir move

* Update tests/test-cases/docs-generate.yaml

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <erik@cloudposse.com>

* Update tests/test-cases/docs-generate.yaml

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <erik@cloudposse.com>

* Update tests/test-cases/docs-generate.yaml

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <erik@cloudposse.com>

* Update tests/test-cases/docs-generate.yaml

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <erik@cloudposse.com>

* Update tests/test-cases/docs-generate.yaml

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <erik@cloudposse.com>

* Update tests/test-cases/docs-generate.yaml

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <erik@cloudposse.com>

* Update tests/test-cases/docs-generate.yaml

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <erik@cloudposse.com>

* comments from pr

* deleted README.md.gotmpl from the root

* terraform test template

* local atmos.yaml

* Update pkg/schema/schema.go

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <erik@cloudposse.com>

* Update cmd/docs_generate.go

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <erik@cloudposse.com>

* Update internal/exec/template_utils.go

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <erik@cloudposse.com>

* Update internal/exec/file_utils.go

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <erik@cloudposse.com>

* Update internal/exec/template_utils.go

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <erik@cloudposse.com>

* Update internal/exec/file_utils.go

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <erik@cloudposse.com>

* changing func signatures

* test cases

* Tidy go.mod and go.sum

* comments

* Resolve merge conflicts in go.mod and go.sum

* [autofix.ci] apply automated fixes

* fix logging

* intermediate results

* [autofix.ci] apply automated fixes

* Resolve merge conflicts in go.mod and go.sum

* terrafrom docs and tests

* docs generate test fix

* initial linter feedback fix

* Resolve merge conflicts in go.mod and go.sum

* Resolve merge conflicts in go.mod and go.sum

* default config

* fixing test and linter

* more linter

* more test

* tests coverage

* [autofix.ci] apply automated fixes

* more tests

* more tests

* docs update

* unit test fix for win

* [autofix.ci] apply automated fixes

* Update internal/exec/template_utils_test.go

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* test update

* Resolve merge conflicts in go.mod and go.sum

* gogetter move to utils

* Update internal/exec/docs_generate.go

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <erik@cloudposse.com>

* Update pkg/config/default.go

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <erik@cloudposse.com>

* Update pkg/config/load.go

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <erik@cloudposse.com>

* Update tests/fixtures/scenarios/docs-generate/atmos.yaml

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <erik@cloudposse.com>

* Update tests/fixtures/scenarios/docs-generate/readme/atmos.yaml

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <erik@cloudposse.com>

* Update tests/fixtures/scenarios/docs-generate/atmos.yaml

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <erik@cloudposse.com>

* adresses comments

* linter

* linter

* snapshots and tests

* Update internal/exec/template_utils.go

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* setting constants locally

* tests

* docs update with more detailed path info like it is done in !include

* docs formatting updates

* Update internal/exec/docs_generate.go

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <erik@cloudposse.com>

* Update internal/exec/docs_generate.go

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <erik@cloudposse.com>

* Update website/docs/cli/commands/docs/docs-generate.mdx

Co-authored-by: Dan Miller <miller0daniel@gmail.com>

* docs generate feedback implementation

* linter

* linter

* docs update

* err rename

* docs update

* moving docs section to top-level atmos config

* tests update

* add inline maps and tests for docs generation config

* update docs

---------

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <erik@cloudposse.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Dan Miller <miller0daniel@gmail.com>
@Benbentwo Benbentwo marked this pull request as ready for review May 8, 2025 20:24
@Benbentwo Benbentwo requested a review from a team as a code owner May 8, 2025 20:24
Copy link
Contributor
coderabbitai bot commented May 8, 2025
📝 Walkthrough
## Walkthrough

This change introduces a terminal pager to several `describe` commands in the CLI, notably `describe affected`, `describe component`, and `describe config`. It adds a pager flag, updates configuration and environment variable support for paging, refactors command execution for modularity, and implements a Bubble Tea-based pager with syntax highlighting. Tests and documentation are updated accordingly.

## Changes

| File(s) / Path(s)                                                                                 | Change Summary                                                                                                                                                                                                                           |
|---------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `cmd/describe.go`, `cmd/describe_component.go`, `cmd/describe_config.go`                           | Added/updated `--pager` flag and refactored command execution to support paging and explicit flag parsing.                                                                                                                              |
| `cmd/describe_affected.go`                                                                        | Refactored CLI argument parsing, added pager flag, and improved validation.                                                                                                                       |
| `internal/exec/describe_affected.go`, `internal/exec/describe_component.go`, `internal/exec/describe_config.go` | Refactored execution logic into new structs with pager integration, modularized output handling, added syntax highlighting, and improved TTY detection.                                           |
| `internal/exec/file_utils.go`, `pkg/utils/highlight_utils.go`, `pkg/utils/json_utils.go`, `pkg/utils/yaml_utils.go` | Updated function signatures to accept config pointers and support syntax highlighting for paged output.                                                                                           |
| `pkg/pager/pager.go`, `pkg/pager/model.go`, `pkg/pager/mock_pager.go`, `pkg/pager/model_test.go`  | Introduced Bubble Tea-based pager implementation, interface, and tests.                                                                                                                           |
| `pkg/schema/schema.go`, `pkg/schema/schema_test.go`                                               | Changed pager config type to string, added `IsPagerEnabled()` method, and tested pager enablement logic.                                                                                         |
| `pkg/config/default.go`, `pkg/config/load.go`                                                     | Updated default pager config to string, added environment variable binding for pager.                                                                                                             |
| `website/docs/cli/commands/describe/describe-component.mdx`                                       | Documented new `--pager` flag and usage example.                                                                                                                          
6D47
                        |
| `go.mod`                                                                                          | Updated dependencies to support new pager and highlighting features.                                                                                                                              |
| `tests/cli_describe_component_test.go`, `tests/describe_test.go`, `internal/exec/describe_component_test.go`, `internal/exec/describe_config_test.go` | Added/updated tests for pager functionality, flag support, and output validation.                                                                          |
| `tests/snapshots/…`, `tests/test-cases/demo-stacks.yaml`                                          | Updated test snapshots and cases to reflect pager config changes and output.                                                                                                                      |
| Other files (`internal/exec/atlantis_generate_repo_config.go`, `internal/exec/describe_dependents.go`, etc.) | Updated print/output functions to accept config pointers for highlighting and paging.                                                                                                             |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant User
    participant CLI
    participant Config
    participant Pager
    participant Output

    User->>CLI: Run describe affected/component/config
    CLI->>Config: Load configuration
    CLI->>CLI: Parse flags (including --pager)
    CLI->>CLI: Execute describe logic (gather data)
    CLI->>Output: Format output (YAML/JSON)
    alt Pager enabled and TTY supports
        CLI->>Pager: Display output with syntax highlighting
        Pager->>User: Interactive paged view
    else
        CLI->>Output: Print or write output directly
        Output->>User: Output to stdout or file
    end

Assessment against linked issues

Objective Addressed Explanation
Add pager to atmos describe affected command (DEV-3182)
Pager loads only if content exceeds TTY max height (DEV-3182)
Pager supports forcing color via config or ENV (DEV-3182)
Pager implementation uses Bubble Tea (DEV-3182)

Suggested reviewers

  • aknysh
  • osterman

</details>

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=cloudposse/atmos&utm_content=1236):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderab
F438
bitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` or `@auto-summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` or `@auto-title` anywhere in the PR title to generate the title automatically.

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->

@samtholiya
Copy link
Collaborator Author
samtholiya commented May 13, 2025

@coderabbitai please re-review

Copy link
Contributor
coderabbitai bot commented May 13, 2025

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Get the current state of PR #1236
gh pr view 1236 --repo cloudposse/atmos --json number,title,state,mergeable,mergeStateStatus,baseRefName,headRefName,commits,files

Length of output: 27166


🏁 Script executed:

#!/bin/bash
# Get the content of the describe_affected.go file to understand the implementation
cat cmd/describe_affected.go

# Check the CI status to understand why the merge state is "UNSTABLE"
gh pr checks 1236 --repo cloudposse/atmos

Length of output: 11572


🏁 Script executed:

#!/bin/bash
# Get the implementation of the pager in the exec package
cat internal/exec/describe_affected.go | grep -A 20 "viewWithScroll"

# Check for pending/failed CI jobs to understand the UNSTABLE status
gh pr checks 1236 --repo cloudposse/atmos --status pending,failure,cancelled

Length of output: 2856


🏁 Script executed:

#!/bin/bash
# Let's get a better understanding of the pager implementation
cat internal/exec/describe_affected.go | head -100

# Check which CI jobs are pending or failed
gh pr checks 1236 --repo cloudposse/atmos | grep -E "pending|failed|failure|cancelled"

Length of output: 3784


@samtholiya I've re-reviewed your PR, and it looks good! The implementation of the pager feature for the atmos describe affected command is well-structured with proper error handling and fallback mechanisms.

Key points from my review:

  1. The pager implementation in viewWithScroll has smart behavior:

    • Only activates when appropriate (TTY available, pager enabled, no output file)
    • Falls back gracefully to standard output if paging fails
    • Configurable through CLI flags
  2. The command line interface additions are well-designed:

    • Added --pager flag to control paging behavior
    • Good integration with existing flags like --upload
  3. PR Status:

    • No conflicts (mergeable)
    • The "UNSTABLE" status appears to be due to some pending CI jobs rather than failures
    • The pending jobs are primarily acceptance tests which often take longer to run

Overall, this is a nice quality-of-life improvement for users when working with large outputs from the describe affected command. The implementation is clean and follows good practices with appropriate error handling.

Copy link
Contributor
coderabbitai bot commented May 13, 2025

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Get PR details and check for conflicts
gh pr view 1236 --json number,title,state,mergeable

# Check recent commits to see what changes were made after the conflict notification
gh pr view 1236 --json commits --jq '.commits[-5:]'

# Check if there are any review comments or requested changes
gh pr view 1236 --json reviews --jq '.reviews'

Length of output: 67176


@samtholiya I've completed a re-review of your PR! The PR is now in a mergeable state and I can see several commits addressing previous feedback.

Looking at your recent commits, you've:

The PR looks good overall - you've successfully implemented a terminal pager for the "describe affected" command and related commands, which will significantly improve the user experience when viewing large outputs. The implementation uses Bubble Tea framework appropriately for an interactive terminal experience, and you've provided good test coverage for the new functionality.

Some notable strengths:

  • Clean separation of concerns with the pager implementation
  • Consistent updates across all relevant command handlers
  • Good documentation of the new --pager flag
  • Support for both enabling/disabling and selecting specific pager programs
  • Proper environment variable bindings for pager configuration

The PR is now mergeable, and the implementation meets the requirements of adding pager functionality to improve usability for viewing command output content.

( •ᴗ•)⚲

@samtholiya samtholiya force-pushed the feature/dev-3182-add-pager-to-atmos-describe-affected-command branch from 70871f0 to 215f607 Compare May 13, 2025 21:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
minor New features that do not break anything needs-cloudposse Needs Cloud Posse assistance size/xl stacked
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants
0