Skip to content

Commit

Permalink
Merge pull request #31 from rafaelldi/env-vars
Browse files Browse the repository at this point in the history
Improved handling of environment variables from Aspire host launchSettings file
  • Loading branch information
rafaelldi authored Jan 9, 2024
2 parents 03acd26 + 9751479 commit d6aa847
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 18 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

## [Unreleased]

### Changed

- Improved handling of environment variables from Aspire host launchSettings file

## [0.2.1] - 2024-01-05

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pluginGroup = me.rafaelldi.aspire
pluginName = aspire-plugin
pluginRepositoryUrl = https://github.com/rafaelldi/aspire-plugin
# SemVer format -> https://semver.org
pluginVersion = 0.2.1
pluginVersion = 0.2.2

# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
pluginSinceBuild = 233
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class AspireHostConfigurationFactory(type: AspireHostConfigurationType) :
this,
"Aspire Host",
AspireHostConfigurationParameters(
project, "", true, DotNetStartBrowserParameters()
project, "", true, hashMapOf(), true, DotNetStartBrowserParameters()
)
)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package me.rafaelldi.aspire.run

import com.intellij.execution.configuration.EnvironmentVariablesComponent
import com.intellij.execution.configurations.RunConfiguration
import com.intellij.execution.configurations.RunProfile
import com.intellij.execution.configurations.RuntimeConfigurationError
Expand All @@ -20,11 +21,14 @@ import org.jdom.Element
class AspireHostConfigurationParameters(
private val project: Project,
var projectFilePath: String,
var trackEnvs: Boolean,
var envs: Map<String, String>,
var trackUrl: Boolean,
var startBrowserParameters: DotNetStartBrowserParameters
) {
companion object {
private const val PROJECT_FILE_PATH = "PROJECT_FILE_PATH"
private const val TRACK_ENVS = "TRACK_ENVS"
private const val TRACK_URL = "TRACK_URL"
}

Expand Down Expand Up @@ -56,22 +60,29 @@ class AspireHostConfigurationParameters(

fun readExternal(element: Element) {
projectFilePath = JDOMExternalizerUtil.readField(element, PROJECT_FILE_PATH) ?: ""
val trackEnvsString = JDOMExternalizerUtil.readField(element, TRACK_ENVS) ?: ""
trackEnvs = trackEnvsString != "0"
EnvironmentVariablesComponent.readExternal(element, envs)
val trackUrlString = JDOMExternalizerUtil.readField(element, TRACK_URL) ?: ""
trackUrl = trackUrlString != "0"
startBrowserParameters = DotNetStartBrowserParameters.readExternal(element)
}

fun writeExternal(element: Element) {
JDOMExternalizerUtil.writeField(element, PROJECT_FILE_PATH, projectFilePath)
JDOMExternalizerUtil.writeField(element, TRACK_ENVS, if (trackEnvs) "1" else "0")
EnvironmentVariablesComponent.writeExternal(element, envs)
JDOMExternalizerUtil.writeField(element, TRACK_URL, if (trackUrl) "1" else "0")
startBrowserParameters.writeExternal(element)
}
}

fun AspireHostConfigurationParameters.setUpFromRunnableProject(project: RunnableProject) {
projectFilePath = project.projectFilePath
trackUrl = true
val runOptions = project.getRunOptions()
trackEnvs = true
envs = project.environmentVariables.associate { it.key to it.value }
trackUrl = true
val startBrowserUrl = runOptions.startBrowserUrl
if (startBrowserUrl.isNotEmpty()) {
startBrowserParameters.apply {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,23 @@ class AspireHostConfigurationViewModel(
private val lifetime: Lifetime,
private val runnableProjectsModel: RunnableProjectsModel?,
val projectSelector: ProjectSelector,
val environmentVariablesEditor: EnvironmentVariablesEditor,
separator: ViewSeparator,
val urlEditor: TextEditor,
val dotNetBrowserSettingsEditor: BrowserSettingsEditor
) : RunConfigurationViewModelBase() {
override val controls: List<ControlBase> =
listOf(
projectSelector,
environmentVariablesEditor,
separator,
urlEditor,
dotNetBrowserSettingsEditor
)

private var isLoaded = false

var trackEnvs = true
var trackUrl = true

init {
Expand All @@ -44,6 +48,7 @@ class AspireHostConfigurationViewModel(
)
}

environmentVariablesEditor.envs.advise(lifetime) { handleEnvValueChange() }
urlEditor.text.advise(lifetime) { handleUrlValueChange() }
}

Expand All @@ -53,6 +58,7 @@ class AspireHostConfigurationViewModel(
}

val runOptions = project.getRunOptions()
environmentVariablesEditor.envs.set(runOptions.environmentVariables)
val startBrowserUrl = runOptions.startBrowserUrl
if (startBrowserUrl.isNotEmpty()) {
urlEditor.defaultValue.value = startBrowserUrl
Expand All @@ -61,16 +67,31 @@ class AspireHostConfigurationViewModel(
}
}

private fun handleEnvValueChange() {
projectSelector.project.valueOrNull?.let {
val envs = it.environmentVariables.associate { pair -> pair.key to pair.value }.toSortedMap()
val editorEnvs = environmentVariablesEditor.envs.value.toSortedMap()
trackEnvs = envs == editorEnvs
}
}

private fun handleUrlValueChange() {
projectSelector.project.valueOrNull?.let {
val runOptions = it.getRunOptions()
trackUrl = urlEditor.text.value == runOptions.startBrowserUrl
}
}

fun reset(projectFilePath: String, trackUrl: Boolean, dotNetStartBrowserParameters: DotNetStartBrowserParameters) {
fun reset(
projectFilePath: String,
trackEnvs: Boolean,
envs: Map<String, String>,
trackUrl: Boolean,
dotNetStartBrowserParameters: DotNetStartBrowserParameters
) {
isLoaded = false

this.trackEnvs = trackEnvs
this.trackUrl = trackUrl

runnableProjectsModel?.projects?.adviseOnce(lifetime) { projectList ->
Expand Down Expand Up @@ -116,6 +137,10 @@ class AspireHostConfigurationViewModel(
}?.let { project ->
projectSelector.project.set(project)

val effectiveEnvs =
if (trackEnvs) project.environmentVariables.associate { it.key to it.value } else envs
environmentVariablesEditor.envs.set(effectiveEnvs)

val runOptions = project.getRunOptions()
val effectiveUrl = if (trackUrl) runOptions.startBrowserUrl else dotNetStartBrowserParameters.url
urlEditor.defaultValue.value = effectiveUrl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,18 @@ import com.jetbrains.rider.model.runnableProjectsModel
import com.jetbrains.rider.projectView.solution
import com.jetbrains.rider.run.configurations.AsyncExecutorFactory
import com.jetbrains.rider.run.configurations.project.DotNetProjectConfigurationParameters
import com.jetbrains.rider.run.environment.ExecutableParameterProcessor
import com.jetbrains.rider.run.environment.ExecutableRunParameters
import com.jetbrains.rider.run.environment.ProjectProcessOptions
import com.jetbrains.rider.runtime.DotNetExecutable
import com.jetbrains.rider.runtime.RiderDotNetActiveRuntimeHost
import com.jetbrains.rider.util.NetUtils
import me.rafaelldi.aspire.run.AspireHostProgramRunner.Companion.DEBUG_SESSION_PORT
import me.rafaelldi.aspire.run.AspireHostProgramRunner.Companion.DEBUG_SESSION_TOKEN
import me.rafaelldi.aspire.run.AspireHostProgramRunner.Companion.DOTNET_DASHBOARD_OTLP_ENDPOINT_URL
import me.rafaelldi.aspire.settings.AspireSettings
import org.jetbrains.concurrency.await
import java.io.File
import java.util.*

class AspireHostExecutorFactory(
Expand Down Expand Up @@ -50,13 +55,11 @@ class AspireHostExecutorFactory(
}
}

private fun getDotNetExecutable(runnableProject: RunnableProject): DotNetExecutable {
private suspend fun getDotNetExecutable(runnableProject: RunnableProject): DotNetExecutable {
val projectOutput = runnableProject.projectOutputs.firstOrNull()
?: throw CantRunException("Unable to find project output")
val envs = runnableProject.environmentVariables
.associate { it.key to it.value }
.toMutableMap()

val envs = parameters.envs.toMutableMap()
val debugSessionToken = UUID.randomUUID().toString()
val debugSessionPort = NetUtils.findFreePort(67800)
val openTelemetryProtocolEndpointPort = NetUtils.findFreePort(87800)
Expand All @@ -65,14 +68,32 @@ class AspireHostExecutorFactory(
if (AspireSettings.getInstance().collectTelemetry)
envs[DOTNET_DASHBOARD_OTLP_ENDPOINT_URL] = "http://localhost:$openTelemetryProtocolEndpointPort"

return DotNetExecutable(
val processOptions = ProjectProcessOptions(
File(runnableProject.projectFilePath),
File(projectOutput.workingDirectory)
)
val runParameters = ExecutableRunParameters(
projectOutput.exePath,
projectOutput.tfm,
projectOutput.workingDirectory,
ParametersListUtil.join(projectOutput.defaultArguments),
envs,
true,
projectOutput.tfm
)

val params = ExecutableParameterProcessor
.getInstance(project)
.processEnvironment(runParameters, processOptions)
.await()

return DotNetExecutable(
params.executablePath ?: projectOutput.exePath,
params.tfm ?: projectOutput.tfm,
params.workingDirectoryPath ?: projectOutput.workingDirectory,
params.commandLineArgumentString ?: ParametersListUtil.join(projectOutput.defaultArguments),
false,

Check notice on line 94 in src/main/kotlin/me/rafaelldi/aspire/run/AspireHostExecutorFactory.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Boolean literal argument without parameter name

Boolean literal argument without a parameter name
false,

Check notice on line 95 in src/main/kotlin/me/rafaelldi/aspire/run/AspireHostExecutorFactory.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Boolean literal argument without parameter name

Boolean literal argument without a parameter name
envs,
params.environmentVariables,
true,
parameters.startBrowserAction,
null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@ package me.rafaelldi.aspire.run
import com.intellij.openapi.project.Project
import com.jetbrains.rd.util.lifetime.Lifetime
import com.jetbrains.rider.run.configurations.ProtocolLifetimedSettingsEditor
import com.jetbrains.rider.run.configurations.controls.ControlViewBuilder
import com.jetbrains.rider.run.configurations.controls.ProjectSelector
import com.jetbrains.rider.run.configurations.controls.TextEditor
import com.jetbrains.rider.run.configurations.controls.ViewSeparator
import com.jetbrains.rider.run.configurations.controls.*
import com.jetbrains.rider.run.configurations.controls.startBrowser.BrowserSettingsEditor
import com.jetbrains.rider.run.configurations.runnableProjectsModelIfAvailable
import me.rafaelldi.aspire.AspireBundle
import javax.swing.JComponent

class AspireHostSettingsEditor(private val project: Project) :
Expand All @@ -19,9 +17,10 @@ class AspireHostSettingsEditor(private val project: Project) :
viewModel = AspireHostConfigurationViewModel(
lifetime,
project.runnableProjectsModelIfAvailable,
ProjectSelector("Project:", "Project"),
ViewSeparator("Open browser"),
TextEditor("URL", "URL", lifetime),
ProjectSelector(AspireBundle.message("run.editor.project"), "Project"),
EnvironmentVariablesEditor(AspireBundle.message("run.editor.environment.variables"), "Environment_variables"),
ViewSeparator(AspireBundle.message("run.editor.open.browser")),
TextEditor(AspireBundle.message("run.editor.url"), "URL", lifetime),
BrowserSettingsEditor("")
)
return ControlViewBuilder(lifetime, project, "AspireHost").build(viewModel)
Expand All @@ -32,6 +31,8 @@ class AspireHostSettingsEditor(private val project: Project) :
if (selectedProject != null) {
configuration.parameters.apply {
projectFilePath = selectedProject.projectFilePath
trackEnvs = viewModel.trackEnvs
envs = viewModel.environmentVariablesEditor.envs.value
trackUrl = viewModel.trackUrl
startBrowserParameters.url = viewModel.urlEditor.text.value
startBrowserParameters.browser = viewModel.dotNetBrowserSettingsEditor.settings.value.myBrowser
Expand All @@ -47,6 +48,8 @@ class AspireHostSettingsEditor(private val project: Project) :
configuration.parameters.apply {
viewModel.reset(
projectFilePath,
trackEnvs,
envs,
trackUrl,
startBrowserParameters
)
Expand Down
5 changes: 5 additions & 0 deletions src/main/resources/messages/AspireBundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ action.Aspire.Settings.description=Open plugin settings page
action.Aspire.Help.text=Aspire Help
action.Aspire.Help.description=Open plugin help

run.editor.project=Project:
run.editor.environment.variables=Environment variables:
run.editor.open.browser=Open browser
run.editor.url=URL

configurable.Aspire=Aspire
configurable.Aspire.check.new.version=Check for new versions of the Aspire workload during startup
configurable.Aspire.show.service=Show projects in the Services tool window
Expand Down

0 comments on commit d6aa847

Please sign in to comment.