Skip to content

Commit

Permalink
Merge pull request #57 from rafaelldi/manifest
Browse files Browse the repository at this point in the history
Add generate manifest action
  • Loading branch information
rafaelldi authored Feb 7, 2024
2 parents 5384fb5 + e24e764 commit cb7b3ff
Show file tree
Hide file tree
Showing 8 changed files with 185 additions and 1 deletion.
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]

### Added

- Generate Aspire manifest action

## [0.2.3] - 2024-01-22

### Fixed
Expand Down
26 changes: 26 additions & 0 deletions src/dotnet/aspire-plugin/Project/AspireHostExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using JetBrains.Application;
using JetBrains.ProjectModel;
using JetBrains.ProjectModel.ProjectsHost;
using JetBrains.ProjectModel.Properties;
using JetBrains.RdBackend.Common.Features.ProjectModel.View;
using JetBrains.Util;

namespace AspirePlugin.Project;

[ShellComponent]
public class AspireHostExtension : ProjectModelViewPresenterExtension
{
public override bool TryAddUserData(IProjectMark projectMark, IProject? project, out string name, out string value)
{
var property = project?.GetUniqueRequestedProjectProperty(AspireHostProjectPropertyRequest.IsAspireHost);
if (property.IsNullOrEmpty())
{
return base.TryAddUserData(projectMark, project, out name, out value);
}

name = AspireHostProjectPropertyRequest.IsAspireHost;
value = property;

return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Collections.Generic;
using JetBrains.Application;
using JetBrains.Application.Parts;
using JetBrains.ProjectModel.Properties;

namespace AspirePlugin.Project;

[ShellComponent(Instantiation.DemandAnyThreadSafe)]
public class AspireHostProjectPropertyRequest : IProjectPropertiesRequest
{
public const string IsAspireHost = "IsAspireHost";
public IEnumerable<string> RequestedProperties => new[] { IsAspireHost };
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package me.rafaelldi.aspire.actions

import com.intellij.openapi.actionSystem.ActionUpdateThread
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.platform.backend.workspace.virtualFile
import com.jetbrains.rider.model.RdProjectDescriptor
import com.jetbrains.rider.projectView.nodes.getUserData
import com.jetbrains.rider.projectView.workspace.getProjectModelEntity
import com.jetbrains.rider.runtime.RiderDotNetActiveRuntimeHost
import me.rafaelldi.aspire.manifest.ManifestService

class ManifestGenerationAction : AnAction() {
override fun actionPerformed(event: AnActionEvent) {
val project = event.project ?: return
val entity = event.dataContext.getProjectModelEntity() ?: return
val descriptor = entity.descriptor as? RdProjectDescriptor ?: return
if (!descriptor.isDotNetCore) return
val isAspireHost = descriptor.getUserData("IsAspireHost")
if (isAspireHost?.equals("true", true) != true) return
val file = entity.url?.virtualFile ?: return

ManifestService.getInstance(project).generateManifest(file.toNioPath())
}

override fun update(event: AnActionEvent) {
val project = event.project
if (project == null) {
event.presentation.isEnabledAndVisible = false
return
}

val runtime = RiderDotNetActiveRuntimeHost.getInstance(project).dotNetCoreRuntime.value
if (runtime == null) {
event.presentation.isEnabledAndVisible = false
return
}

val entity = event.dataContext.getProjectModelEntity()
val descriptor = entity?.descriptor
if (descriptor == null || descriptor !is RdProjectDescriptor || !descriptor.isDotNetCore) {
event.presentation.isEnabledAndVisible = false
return
}

val isAspireHost = descriptor.getUserData("IsAspireHost")
if (isAspireHost?.equals("true", true) != true) {
event.presentation.isEnabledAndVisible = false
return
}

event.presentation.isEnabledAndVisible = true
}

override fun getActionUpdateThread() = ActionUpdateThread.BGT
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class DiagramService(private val project: Project) {
initSelectionListeners()
initToolbarActions(title)
}).thenAccept {
val diagramState = DiagramState(title, it.first)
val diagramState = DiagramState(it.first)
diagramState.generateGroups()
diagramState.applyChanges()

Expand Down
76 changes: 76 additions & 0 deletions src/main/kotlin/me/rafaelldi/aspire/manifest/ManifestService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
@file:Suppress("UnstableApiUsage")

package me.rafaelldi.aspire.manifest

import com.intellij.execution.util.ExecUtil
import com.intellij.ide.util.PsiNavigationSupport
import com.intellij.notification.Notification
import com.intellij.notification.NotificationType
import com.intellij.openapi.components.Service
import com.intellij.openapi.components.service
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.project.Project
import com.intellij.openapi.rd.util.withUiContext
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.platform.ide.progress.withBackgroundProgress
import com.jetbrains.rider.runtime.RiderDotNetActiveRuntimeHost
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import me.rafaelldi.aspire.AspireBundle
import java.nio.file.Path
import kotlin.io.path.absolutePathString

@Service(Service.Level.PROJECT)
class ManifestService(private val project: Project, private val scope: CoroutineScope) {
companion object {
fun getInstance(project: Project) = project.service<ManifestService>()
private val LOG = logger<ManifestService>()

private const val MANIFEST_FILE_NAME = "aspire-manifest.json"
}

fun generateManifest(hostProjectPath: Path) {
scope.launch(Dispatchers.Default) {
withBackgroundProgress(project, AspireBundle.message("progress.generating.aspire.manifest")) {
val runtime = RiderDotNetActiveRuntimeHost.getInstance(project).dotNetCoreRuntime.value
if (runtime == null) {
LOG.warn("Unable to find .NET runtime")
return@withBackgroundProgress
}

val commandLine = runtime.createCommandLine(
listOf(
"msbuild",
"/t:GenerateAspireManifest",
"/p:AspireManifestPublishOutputPath=$MANIFEST_FILE_NAME"
)
)
val directoryPath = hostProjectPath.parent
commandLine.workDirectory = directoryPath.toFile()
LOG.debug(commandLine.commandLineString)

val output = ExecUtil.execAndGetOutput(commandLine)
if (output.checkSuccess(LOG)) {
val manifestPath = directoryPath.resolve(MANIFEST_FILE_NAME)
val file = LocalFileSystem.getInstance().refreshAndFindFileByPath(manifestPath.absolutePathString())
if (file != null && file.isValid) {
withUiContext {
PsiNavigationSupport.getInstance().createNavigatable(project, file, -1).navigate(true)
}
}
} else {
withUiContext {
Notification(
"Aspire",
AspireBundle.message("notification.manifest.unable.to.generate"),
output.stderr,
NotificationType.WARNING
)
.notify(project)
}
}
}
}
}
}
5 changes: 5 additions & 0 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@
<action id="Aspire.Diagram"
class="me.rafaelldi.aspire.actions.ShowDiagramAction"
icon="AllIcons.FileTypes.Diagram"/>
<action id="Aspire.Manifest"
class="me.rafaelldi.aspire.actions.ManifestGenerationAction"
icon="AllIcons.Actions.PrettyPrint">
<add-to-group group-id="SolutionExplorerPopupMenu.Tools"/>
</action>
</actions>

</idea-plugin>
4 changes: 4 additions & 0 deletions src/main/resources/messages/AspireBundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ action.Aspire.Dashboard.text=Open Aspire Dashboard
action.Aspire.Dashboard.description=Open Aspire dashboard in browser
action.Aspire.Diagram.text=Show Diagram
action.Aspire.Diagram.description=Show distributed traces diagram
action.Aspire.Manifest.text=Generate Aspire Manifest
action.Aspire.Manifest.description=Generate .NET Aspire manifest

run.editor.project=Project:
run.editor.environment.variables=Environment variables:
Expand All @@ -20,13 +22,15 @@ configurable.Aspire.show.service=Show projects in the Services tool window
configurable.Aspire.collect.telemetry=Collect OpenTelemetry data (experimental)

progress.updating.aspire.workload=Updating Aspire workload
progress.generating.aspire.manifest=Generating Aspire Manifest

notification.new.version.is.available=A new version of Aspire workload is available
notifications.update.aspire.workload=Update Aspire workload
notifications.do.not.check.for.updates=Do not check for updates
notifications.aspire.workload.updated=Aspire workload is successfully updated
notifications.aspire.workload.update.failed=Aspire workload update failed
notification.aspire.workload.update.elevated=Rider needs elevated permissions to update workload
notification.manifest.unable.to.generate=Unable to generate Aspire manifest

service.tab.information=Information
service.tab.information.name=Name:
Expand Down

0 comments on commit cb7b3ff

Please sign in to comment.