Skip to content
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

Add Secrets view and deploy with Secrets to extension #2288

Merged
merged 19 commits into from
Sep 20, 2024

Conversation

dotNomad
Copy link
Collaborator

@dotNomad dotNomad commented Sep 18, 2024

This PR adds a new Secrets section to the Home view.

Some new features:

  • Secret values present are sent up on Deploy and added as environment variables on Connect. If the env var is present it's value is overwritten
  • When changing Deployments the provided Secret values are cleared
  • When a successful Deployment occurs the provided Secret values are cleared
  • When a Configuration is changed, but the Deployment stays the same, the shared Secrets keep their values in the UI
  • The number of Secrets with values is displayed as a Count badge on the Secrets section header to help the user know what is going to be sent up
  • When editing a Secret the input will be selected so all of the value is highlighted for easy overwrite (similar to the rename functionality in VS Code)
Preview
CleanShot.2024-09-19.at.16.43.00.mp4

Intent

Resolves #2252, #2257, #2258

Type of Change

    • Bug Fix
    • New Feature
    • Breaking Change
    • Documentation
    • Refactor
    • Tooling

Approach

The approach here was to expand previously made components, and create new ones (when necessary) to allow for the new model of "editing" a Tree Item description.

In this case editing the value of the Secret items.

Actions are used to edit and clear Secrets. Instead of clicking directly the action button is more clear, and avoids issues with duplicated click events when the input field is already up.

When editing a Secret value the action buttons are removed from the UI until editing is complete. This was done to avoid confusing the user and dealing with tricky cases like what clicking "edit" or "clear" should do while the input is open. It also provides more space for the input field which is horizontally constrained.

Directions for Reviewers

Ensure that Tree Item descriptions function and are styled as they previously were.

Ensure the new Tree Item with description input (the Secrets) function as expected.

Ensure that Secrets with values are sent up and are correct on the Connect Server. Secrets without values should remain the same across multiple re-deployments.

Base automatically changed from dotnomad/deploy-with-secrets to main September 18, 2024 21:30
Copy link
Collaborator

@sagerb sagerb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some early feedback, happy to discuss or explain my observations. Thanks!

extensions/vscode/src/views/homeView.ts Show resolved Hide resolved
import { ActionButton } from "src/components/ActionToolbar.vue";

interface Props {
name: string;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would have expected that this component would be a UI component that would accept its name and value through a prop and emit a change when the value changed. I would then have expected the view using this component to have to deal with the storage of the secret value.

While this approach will work, it makes this component extremely dedicated to this particular input vs. having a component that allows its value to be edited. I think we would benefit from having it be a bit more general purpose, especially when you think of using it for environment variables as well.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually started writing it this way at the start, but found it more difficult to keep the home.secrets Map in line with the value that was being v-modeled in Secret.vue instead I made it just reflect the state of home.secrets.get('name') for the name key provided

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main difficulty when using v-model was grabbing the most recent value when swapping over to the input mode. It worked great when setting the value, but not when the value changed out from under the component.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you get a chance to play with the approach we discussed via zoom? That would be where outside component would pass in the map value from the store and then update the store when receiving the change emitted event from the component?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did mess around with this, and it ended up re-creating the Map in the Secrets component a bit as an array so each v-model accessed an index in that array. It felt duplicative to me.

extensions/vscode/webviews/homeView/src/stores/home.ts Outdated Show resolved Hide resolved
@@ -57,6 +60,32 @@ export const useHomeStore = defineStore("home", () => {
},
);

watch(
[selectedContentRecord, selectedConfiguration],
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering about simplifying this into two different watches.

  1. on change of content record, remove all secrets.
  2. on change of config, set the secret from the values present and clear the ones that have gone away.

I've spent a few minutes making sure I understand what your implementation was doing and I think splitting it may avoid that for others in the future.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I initially planned to do this as two separate watches due to the reason you stated, but I was worried about any timing issues that could have spawned from that. For example, some code somewhere could potentially change the content record first then the configuration, and code elsewhere does the opposite potentially leaving secrets in a different state.

Keeping it as I have it avoids that by ensuring secrets is in the correct state no matter if one or both change.

Let me know if I'm making a bad assumption though. I would like to simplify if possible.

Copy link
Collaborator

@sagerb sagerb Sep 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me know if I'm making a bad assumption though. I would like to simplify if possible.

Would the opposite order really end up not equaling the same outcome?

  1. Content-Record changes and then Configuration changes
  • Content-Record change removes all secrets
  • Configuration change has no secrets set, so it does nothing
  1. Configuration changes and then Content-Record changes
  • Configuration change sets the secret from the values present and clears the ones that have gone away
  • Content-Record change removes all secrets

In both cases, no secrets are set after both of these events.

Am I seeing this wrong?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No I think you got it, let me play around with this split into two watches and see if I can break anything. Your logic is sound.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I played around with this a bit, and it ended up being really close to a duplication for both watchers. If you have a code block suggestion we can take a look.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm probably just missing something in my quick analysis, so I'll defer to yours. Let's go with what you've got working. Thanks for indulging me!

@@ -151,6 +155,7 @@ const toggleExpanded = () => {

.tree-item-label-container {
flex: 1;
display: flex;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had to bring in flex for the label container so that the input in the description span could be displayed the way we want. This required bringing down the

min-width: 0;
overflow: hidden;
text-overflow: ellipsis;

CSS for dealing with overflowing with ellipsis.

}

.tree-item-description {
line-height: 22px;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line-height has returned. Now that we are using display: flex here the span is no longer being rendered the same way. Without this the height changes, and the description wasn't on the baseline.

font-size: 0.9em;
margin-left: 0.5em;
opacity: 0.7;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since description can contain an input now we don't want the description to always be opacity: 0.7. Now we apply this only if the description doesn't contain an input (see below)

font-size: 0.9em;
margin-left: 0.5em;
opacity: 0.7;
flex-shrink: 100000;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This retains the behavior we had before where the description would shrink before the title.

Comment on lines +28 to +36
{
label: "Clear Values for all Secrets",
codicon: "codicon-clear-all",
fn: () => {
home.secrets.forEach((_, key) => {
home.secrets.set(key, undefined);
});
},
},
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could optionally show this only if 1 or more secrets have values?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The more I use this the more I want to do this, since the button moves if the count badge is showing or not.

Comment on lines +11 to +13
::selection {
background-color: rgba(195, 183, 184, 0.15);
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This preserves the input selection color, and matches the highlight color across VS Code. This doesn't appear to be a variable, instead it is hardcoded which is interesting. I did check, it is consistent across themes.

@@ -57,6 +60,32 @@ export const useHomeStore = defineStore("home", () => {
},
);

watch(
[selectedContentRecord, selectedConfiguration],
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I played around with this a bit, and it ended up being really close to a duplication for both watchers. If you have a code block suggestion we can take a look.

@dotNomad dotNomad changed the title Dotnomad/secrets view Add Secrets view and deploy with Secrets to extension Sep 19, 2024
@dotNomad dotNomad marked this pull request as ready for review September 19, 2024 23:44
Copy link
Collaborator

@sagerb sagerb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a few responses, which I'll leave to your discretion. I'm approving it so you can determine where you do any followup.

@dotNomad dotNomad merged commit 5e563c7 into main Sep 20, 2024
13 checks passed
@dotNomad dotNomad deleted the dotnomad/secrets-view branch September 20, 2024 23:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Secrets: New UI panel for Secrets
2 participants