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

Allow Environment Shims #19132

Open
jamesstidard opened this issue May 11, 2022 · 6 comments
Open

Allow Environment Shims #19132

jamesstidard opened this issue May 11, 2022 · 6 comments
Labels
area-terminal community ask Feature request that the community expressed interest in feature-request Request for new features or functionality needs proposal Need to make some design decisions

Comments

@jamesstidard
Copy link

jamesstidard commented May 11, 2022

Hi,

There are command line tools that have commands to prepare the shell environment before executing commands. I'm not sure if there's a name for this, but some examples are things like pipenv run, op run, and asdf env.

The main one I'm interested in is 1Password's op run because I'd like to be able to remove the sensitive environment variables I have from my .env files in my projects.

Here's how you might run a pipenv Python project outside of VSCode at the moment using op run

# .env
PYTHONPATH=.
SECRET=op://development/my-service/password
# main.py
import os

print("SECRET", os.environ["SECRET"])
$ pipenv run op run -- python main.py
Loading .env environment variables...
SECRET <concealed by 1Password>

Here pipenv run loads variables found in the projects .env and shims the virtual environment python into the PATH. op run -- then replaces any environment variables with the op:// paths with secrets from the password manager (authenticating their access). python main.py is then executed in this shell environment.

I currently can't see a way of integrating this into my vscode workflow. I've tried:

Would love to have a way to work around this, either with a different method from above, or from dimming down the sanity checks vscode-python does on the "python" argument. Or even better first class support for these kind of environment shims, something complimentary to "python.env" and "python.envFile":

// settings.json
{
    "python.envCommand": ["op", "run", "--"],
}

Could maybe accept a list of commands, if you want to stack environments:

// settings.json
{
    "python.envCommand": [
        ["pipenv", "run"],
        ["op", "run", "--"],
        ["asdf", "run"],
    ],
}

Anyway, quite a niche feature request, I know. But would love to be able to have the ability to do this, and happy to put in the grunt work of implementation, if I can be pointed in the right direction.

@jamesstidard jamesstidard added the feature-request Request for new features or functionality label May 11, 2022
@github-actions github-actions bot added the triage-needed Needs assignment to the proper sub-team label May 11, 2022
@karthiknadig karthiknadig added area-terminal needs community feedback Awaiting community feedback and removed triage-needed Needs assignment to the proper sub-team labels May 12, 2022
@karthiknadig
Copy link
Member

Thanks for the feature request! We are going to give the community 60 days from when this issue was created to provide 7 👍 upvotes on the opening comment to gauge general interest in this idea. If there's enough upvotes then we will consider this feature request in our future planning. If there's unfortunately not enough upvotes then we will close this issue.

@blueshed
Copy link

Another example is preparing a Node virtual environment as well as a python virtual environment on the command line with pypi:NodeEnv. At present I hack the venv/bin/activate to activate the node environment as I cannot access the python.envCommand, in web development of a Vite client to a Python server.

@jamesstidard
Copy link
Author

I cross-posted this onto the 1Password community forums, to try and farm some more eyes 👀.

They use vscode-go which currently does have a way of achieving this. Thought might be useful as a alternative implementation if there's any goals of making the settings interfaces between languages as homogeneous as they can be, for those who are bilingual.

Here's how you can achieve it in vscode-go:

# ~/.op/runners/go
if [ $# -ge 1 ] && ([ $1 = 'run' ] || [ $1 = 'test' ]); then
    op run -- go $@
else
    go $@
fi
// .vscode/settings.json
"go.alternateTools": {
    "go":"~/.op/runners/go"
}

So much like @brettcannon suggestion, but a more sanctioned way.

@brettcannon
Copy link
Member

Thank you to everyone who upvoted this issue! Since the community showed interest in this feature request we will leave this issue open as something to consider implementing at some point in the future.

We do encourage people to continue 👍 the first/opening comment as it helps us prioritize our work based on what the community seems to want the most.

@brettcannon brettcannon added needs proposal Need to make some design decisions community ask Feature request that the community expressed interest in and removed needs community feedback Awaiting community feedback labels Jul 14, 2022
@justmars
Copy link

justmars commented Apr 26, 2023

I'm glad this was brought up as a request: @jamesstidard

Would like to chime in and add what I thought would be viable but didn't pan out. Just adding the relevant bits here re: use of preLaunchTask in relation to variable substitution of a exporting script.

# /src/set.sh
#!/bin/zsh
export GITHUB_ID=$(op read op://dev/auth-local/github/id)
export GITHUB_KEY=$(op read op://dev/auth-local/github/secret)
echo "hello ${GITHUB_ID} ${GITHUB_KEY}" // sanity check
{ // tasks.json
  "tasks": [
    {
      "label": "generateSecretReferences",
      "type": "shell",
      "command": "${workspaceFolder}/src/set.sh",
      "problemMatcher": []
    }
  ]
}
{ // launch.json
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Python: 1Password Django",
      "cwd": "${workspaceFolder}/src",
      "preLaunchTask": "generateSecretReferences",
      "env": {
        "GITHUB_ID": "${env:GITHUB_ID}", // var substitution attempt
        "GITHUB_KEY": "${env:GITHUB_KEY}",
      }
    },
  ]
}

Through this route, the preLaunchTask successfully echoes the exported environment GITHUB_ID and GITHUB_KEY from 1Password. I tried vscode's variable substitution syntax to pipe the exported values back to the launch.json where Django was running and added a print function to see if the latter environment would show the values:

# src/manage.py
def main():
    """Run administrative tasks."""
    ...
    print(f"{os.environ.get('GITHUB_ID')=} {os.environ.get('GITHUB_KEY')=}")
    execute_from_command_line(sys.argv)

if __name__ == "__main__":
    main()

No dice. Result:

 *  Executing task: /src/set.sh 

hello id-from-sanity-check key-from-sanity-check

# then it clears the window
# debug session starts

./.vscode/extensions/ms-python.python-2023.6.1/pythonFiles/lib/python/debugpy/adapter/../../debugpy/launcher 50892 -- 
....
os.environ.get('GITHUB_ID')='' os.environ.get('GITHUB_KEY')=''
Performing system checks...
...

So I'm guessing the preLaunchTask's environment where 1Password values were echoed, is a totally separate environment from the debug session proper where empty values were printed out when Django runserver was invoked.

Adding this tidbit in case it's helpful.

@MichaelMHoff
Copy link

The issue also got raised in the op-vscode extension and unfortunately there is still no solution. Shims (as posted above) still appear to be the best way to do it, but vscode-python rejects them without further information.

In my case, the shim even worked for a few runs and then launches simply began quitting without any error produced by VS Code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-terminal community ask Feature request that the community expressed interest in feature-request Request for new features or functionality needs proposal Need to make some design decisions
Projects
None yet
Development

No branches or pull requests

6 participants