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

Conda Environment task #7075

Merged
merged 61 commits into from
May 16, 2018
Merged

Conda Environment task #7075

merged 61 commits into from
May 16, 2018

Conversation

brcrista
Copy link
Contributor

@brcrista brcrista commented Apr 25, 2018

image

Testing

  • L0
  • Manually on self-hosted Windows and Linux, using both pre-existing Conda installations and installing the lastest Conda
  • Manually on Hosted VS2017 and Hosted macOS

@hashtagchris
Copy link
Contributor

For persistent self hosted agents, if our task installs Conda, will $CONDA be set the next time the task runs and prevent install/update to newer versions?

@davidstaheli
Copy link
Contributor

Regarding @hashtagchris' comment, when Miniconda gets installed, could it be installed in the tool cache so that it sticks around between builds on self-hosted agents? The task could look in this order to find 'conda' at runtime: $CONDA, then the tool cache, then download it.

@hashtagchris
Copy link
Contributor

BTW, I meant to suggest that preventing the update of newer versions is generally a bad thing. :)

My thinking: If conda was installed by a previous task execution and installConda is still checked, let's call conda update --name base conda --yes unless it takes a long time. If conda was installed independently, let's leave it alone.

@brcrista
Copy link
Contributor Author

@hashtagchris @davidstaheli What David said from the folks he talked to at Anaconda Con, there doesn't seem to be much value in providing access to older / side-by-side versions of Conda.

Version slippage on private agents is a problem. I like the idea of the task handling update. I say we change "Install Conda if missing" to "Get latest Conda." It will install if it's missing, or if it finds an existing one, will go ahead and update it.

Regarding $CONDA, I don't know of any way for the task to set a system variable on the host machine like that. I don't know if that's even desirable. So right now, all it does is set $CONDA for the rest of the build process. We could just hardcode the task to go look where it installs Conda if $CONDA isn't set. Open to suggestions here.


interface TaskParameters {
environmentName: string,
packageSpecs?: string
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: there's a missing comma here. I'm kinda surprised typescript didn't catch this. I guess this is just a lint error? Are you running a lint check?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Weird! I thought that would be a syntax error. I should probably take the time to set up a linter.

installConda?: boolean
}

export async function condaEnvironment(parameters: Readonly<TaskParameters>, platform: Platform): Promise<void> {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: I feel like this could have a better name. condaEnvironment is a function without a verb in the name: useCondaEnvironment or the like would be an improvement, IMO.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I named the function for the task. The pattern here is that main.ts communicates with the task runner, and this function contains the actual implementation for the task.

To the point, perhaps the name of the task could have a verb in it. We could say "Activate Conda Environment," but that makes it sound like the environment has to exist already.

Copy link
Contributor

Choose a reason for hiding this comment

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

I feel that code should read like code. To me, that's more important than this matching a design pattern. Conda Environment may make sense as a name for a task, but it doesn't make sense as a function. If you feel that this pattern is important enough to change the name of the task, I'd support that decision; I don't think that the name of the task should dictate the name of the function in the code if makes the code read weird.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I see your point, but here's why I don't think it sounds so weird:

There's a paradigm where "variables are nouns and functions are verbs." But would you rather say father('Lucas Killgore') or const father = getFather('Lucas Killgore')? What about father(mother(father('Lucas Killgore')))? Since your father never changes, the function might as well memoize the result, so you only do the "getting" once -- is it still getFather, or just father now?

My point is, if functions are your main unit of code organization, not all of your functions are verbs. And so the condaEnvironment function is our abstract representation of the task -- just as you would use a class as the abstraction of the task in C#. But JavaScript has made the design decision to make functions easy and classes clunky, thus we use a function.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure I follow your example. I would say getFather. Caching would be an implementation detail. father is a verb, and I would expect it would get the child of Lucas Killgore, which in this case would be null, or empty, or possibly even stuffed panda bears depending on definitions. From your comment, I would expect that you would think it should return Darth Vader. In any case, leaving 'get' off makes the call ambiguous.

FWIW, this would be fine to me: const environment = new CondaEnvironment(); environment.set();.

I think it comes down to me disagreeing with the central conceit: 'if functions are your main unit of code organization, not all of your functions are verbs'. No, I think they should be, or at least, this is not an exception to that case.


// By default `downloadTool` will name the downloaded file with a GUID
// But on Windows, the file must end with `.exe` to make it executable
const tempDirectory = task.getVariable('AGENT_TEMPDIRECTORY');
Copy link
Contributor

@lkillgore lkillgore Apr 26, 2018

Choose a reason for hiding this comment

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

I think it's actually AGENT.TEMPDIRECTORY (at least that seems to be what most other tasks use... I think any . get converted to _ under the covers. Only the tests seem to use _.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Both will work

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure both are 'correct' the only other tasks that use _ are those that by-pass the framework and directly read the environment variable.

Copy link
Contributor

Choose a reason for hiding this comment

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

The dot notation seems more VSTS native to me. For the dot notation, Agent.TempDirectory is the canonical casing. Interesting that this variable isn't documented at https://docs.microsoft.com/en-us/vsts/build-release/concepts/definitions/build/variables

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fair enough. I'll change it to use the dot.

For what it's worth, the Agent.ToolsDirectory variable isn't documented either.

Copy link
Contributor

@lkillgore lkillgore left a comment

Choose a reason for hiding this comment

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

Looks good to me.

@davidstaheli
Copy link
Contributor

Side question:
@TingluoHuang and @ericsciple, should Agent.TempDirectory be documented with other variables at https://docs.microsoft.com/en-us/vsts/build-release/concepts/definitions/build/variables?

@hashtagchris
Copy link
Contributor

I thought it might break a user's expectations if we updated their system's installation of Conda, but FWIW I see that Apple App Store Release updates your system's fastlane using gem update fastlane

@brcrista
Copy link
Contributor Author

After discussing with @madhurig, we decided just to rip out the installer part. It works fine, but our other tasks don't work this way, and it pulls down a 1.5+ GB download. We'll still have the option to keep an existing installation (hosted or private) up-to-date.

Taojunshen pushed a commit to MicrosoftDocs/azure-devops-docs that referenced this pull request May 4, 2018
@brcrista brcrista merged commit 054a710 into master May 16, 2018
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.

4 participants