Skip to content

Commit

Permalink
Pass plugin discoverer output via a temp file
Browse files Browse the repository at this point in the history
  • Loading branch information
prolativ committed Sep 25, 2024
1 parent 2f59f60 commit ba07512
Show file tree
Hide file tree
Showing 11 changed files with 68 additions and 32 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ jobs:
just-version: '1.14.0' # just for sanity
- uses: pulumi/actions@v4
with:
pulumi-version: '3.116.1'
pulumi-version: '3.134.0'
- uses: coursier/[email protected]
- uses: VirtusLab/[email protected]
with:
Expand Down
4 changes: 2 additions & 2 deletions integration-tests/LanguagePluginTest.test.scala
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ class LanguagePluginTest extends munit.FunSuite {
.map(plugin => plugin("name").str -> plugin("version").strOpt.getOrElse("null"))
.toMap

val expectedAboutPluginsVersions = Map("scala" -> "null" /* FIXME */, "random" -> "4.3.1", "aci" -> "0.0.6")
val expectedAboutPluginsVersions = Map("scala" -> scalaPluginVersion, "random" -> "4.3.1", "aci" -> "0.0.6")
assert {
clue(aboutInfoJson)
clue(aboutPluginsVersions) == clue(expectedAboutPluginsVersions)
Expand Down Expand Up @@ -282,7 +282,7 @@ class LanguagePluginTest extends munit.FunSuite {
projectFiles = Map("build.sbt" -> sbtBuildFile)
),
teardown = pulumi.fixture.teardown
).test("sbt".tag(LocalOnly)) { ctx =>
).test("sbt") { ctx =>
testExecutor(ctx)
}

Expand Down
22 changes: 20 additions & 2 deletions language-plugin/bootstrap/PulumiPlugins.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,20 @@ package besom.bootstrap

import scala.util.Using
import scala.jdk.CollectionConverters.*
import java.io.{File, PrintWriter}
import io.github.classgraph.ClassGraph
import besom.json.*

object PulumiPluginsDiscoverer:
def main(args: Array[String]): Unit =
val foundPlugins = pluginsFromClasspath
print(JsArray(foundPlugins.values.toVector).compactPrint)
args.toList match
case Nil =>
print(pluginsJsonText)
case "--output-file" :: outputFilePath :: Nil =>
writeToFile(path = outputFilePath, text = pluginsJsonText)
case _ =>
Console.err.println(s"PulumiPluginDiscoverer: Wrong main arguments: ${args.mkString(",")}")
sys.exit(1)

private val PluginRegex = "^(besom/(.+))/plugin.json$".r

Expand All @@ -27,3 +34,14 @@ object PulumiPluginsDiscoverer:
new ClassGraph()
.filterClasspathElements(_ => true) // todo exclude garbage
.scan()

private def pluginsJsonText =
val foundPlugins = pluginsFromClasspath
JsArray(foundPlugins.values.toVector).compactPrint

private def writeToFile(path: String, text: String): Unit =
val file = new File(path)
val writer = new PrintWriter(file)

writer.write(text)
writer.close()
2 changes: 1 addition & 1 deletion language-plugin/bootstrap/project.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
//> using options -java-output-version:11

//> using dep org.virtuslab::besom-json:0.4.0-SNAPSHOT
//> using dep io.github.classgraph:classgraph:4.8.165
//> using dep io.github.classgraph:classgraph:4.8.176

//> using repository sonatype:snapshots
7 changes: 7 additions & 0 deletions language-plugin/pulumi-language-scala/executors/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package executors

import (
"fmt"
"path"

"github.com/virtuslab/besom/language-host/fsys"
)
Expand Down Expand Up @@ -94,3 +95,9 @@ func (c combinedScalaExecutorFactory) NewScalaExecutor(opts ScalaExecutorOptions
func combineScalaExecutorFactories(variations ...scalaExecutorFactory) scalaExecutorFactory {
return combinedScalaExecutorFactory(variations)
}

const PluginDiscovererOutputFileName = ".besom-pulumi-plugins.json"

func PluginDiscovererOutputFilePath(projectRoot fsys.ParentFS) string {
return path.Join(projectRoot.Path(), PluginDiscovererOutputFileName)
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ func (g gradle) NewScalaExecutor(opts ScalaExecutorOptions) (*ScalaExecutor, err
if err != nil {
return nil, err
}
executor, err := g.newGradleExecutor(gradleRoot, cmd, subproject, opts.BootstrapLibJarPath)
pluginDiscovererOutputPath := PluginDiscovererOutputFilePath(opts.WD)
executor, err := g.newGradleExecutor(gradleRoot, cmd, subproject, opts.BootstrapLibJarPath, pluginDiscovererOutputPath)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -104,21 +105,18 @@ func (gradle) isGradleProject(dir fs.FS, opts ScalaExecutorOptions) (bool, error
return false, nil
}

func (g gradle) newGradleExecutor(gradleRoot fsys.ParentFS, cmd, subproject string, bootstrapLibJarPath string) (*ScalaExecutor, error) {
func (g gradle) newGradleExecutor(gradleRoot fsys.ParentFS, cmd, subproject string, bootstrapLibJarPath string, pluginDiscovererOutputPath string) (*ScalaExecutor, error) {
se := &ScalaExecutor{
Name: "gradle",
Cmd: cmd,
Dir: gradleRoot.Path(),
BuildArgs: []string{g.prefix(subproject, "build"), "--console=plain"},
RunArgs: []string{g.prefix(subproject, "run"), "--console=plain"},
PluginArgs: []string{
/* STDOUT needs to be clean of gradle output,
because we expect a JSON with plugin
results */
"-q", // must go first due to a bug https://github.com/gradle/gradle/issues/5098
g.prefix(subproject, "run"), "--console=plain",
"-PbesomBootstrapJar=" + bootstrapLibJarPath,
"-PmainClass=besom.bootstrap.PulumiPluginsDiscoverer",
"--args=--output-file " + pluginDiscovererOutputPath,
},
VersionArgs: []string{"--version"},
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ func (j jarexec) NewScalaExecutor(opts ScalaExecutorOptions) (*ScalaExecutor, er
if err != nil {
return nil, err
}
return j.newJarExecutor(cmd, opts.BootstrapLibJarPath, opts.Binary)
pluginDiscovererOutputPath := PluginDiscovererOutputFilePath(opts.WD)
return j.newJarExecutor(cmd, opts.BootstrapLibJarPath, opts.Binary, pluginDiscovererOutputPath)
}

func (jarexec) newJarExecutor(cmd string, bootstrapLibJarPath string, rawBinaryPath string) (*ScalaExecutor, error) {
func (jarexec) newJarExecutor(cmd string, bootstrapLibJarPath string, rawBinaryPath string, pluginDiscovererOutputPath string) (*ScalaExecutor, error) {
binaryPath := filepath.Clean(rawBinaryPath)
classPath := bootstrapLibJarPath + ":" + binaryPath

Expand All @@ -37,7 +38,7 @@ func (jarexec) newJarExecutor(cmd string, bootstrapLibJarPath string, rawBinaryP
Cmd: cmd,
BuildArgs: nil, // not supported
RunArgs: []string{"-jar", binaryPath},
PluginArgs: []string{"-cp", classPath, "besom.bootstrap.PulumiPluginsDiscoverer"},
PluginArgs: []string{"-cp", classPath, "besom.bootstrap.PulumiPluginsDiscoverer", "--output-file", pluginDiscovererOutputPath},
VersionArgs: []string{"-version"},
}, nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ func (m maven) NewScalaExecutor(opts ScalaExecutorOptions) (*ScalaExecutor, erro
if err != nil {
return nil, err
}
executor, err := m.newMavenExecutor(cmd, opts.BootstrapLibJarPath)
pluginDiscovererOutputPath := PluginDiscovererOutputFilePath(opts.WD)
executor, err := m.newMavenExecutor(cmd, opts.BootstrapLibJarPath, pluginDiscovererOutputPath)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -58,7 +59,7 @@ func (maven) isMavenProject(opts ScalaExecutorOptions) (bool, error) {
return fsys.FileExists(opts.WD, "pom.xml")
}

func (maven) newMavenExecutor(cmd string, bootstrapLibJarPath string) (*ScalaExecutor, error) {
func (maven) newMavenExecutor(cmd string, bootstrapLibJarPath string, pluginDiscovererOutputPath string) (*ScalaExecutor, error) {
return &ScalaExecutor{
Name: "maven",
Cmd: cmd,
Expand All @@ -75,12 +76,11 @@ func (maven) newMavenExecutor(cmd string, bootstrapLibJarPath string) (*ScalaExe
"scala:run",
},
PluginArgs: []string{
/* move normal output to STDERR, because we need STDOUT for JSON with plugin results */
"-Dorg.slf4j.simpleLogger.logFile=System.err",
"--no-transfer-progress",
"-DbesomBootstrapJar=" + bootstrapLibJarPath,
"-DmainClass=besom.bootstrap.PulumiPluginsDiscoverer",
"scala:run",
"-DaddArgs=--output-file|" + pluginDiscovererOutputPath,
},
VersionArgs: []string{"--version"},
}, nil
Expand Down
15 changes: 7 additions & 8 deletions language-plugin/pulumi-language-scala/executors/executor_sbt.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ func (s sbt) NewScalaExecutor(opts ScalaExecutorOptions) (*ScalaExecutor, error)
if err != nil {
return nil, err
}
return s.newSbtExecutor(cmd, opts.BootstrapLibJarPath)
pluginDiscovererOutputPath := PluginDiscovererOutputFilePath(opts.WD)
return s.newSbtExecutor(cmd, opts.BootstrapLibJarPath, pluginDiscovererOutputPath)
}

func (sbt) isSbtProject(opts ScalaExecutorOptions) (bool, error) {
Expand All @@ -53,31 +54,29 @@ func (sbt) isSbtProject(opts ScalaExecutorOptions) (bool, error) {
return false, nil
}

func (sbt) newSbtExecutor(cmd string, bootstrapLibJarPath string) (*ScalaExecutor, error) {
func (sbt) newSbtExecutor(cmd string, bootstrapLibJarPath string, pluginDiscovererOutputPath string) (*ScalaExecutor, error) {
sbtModule := os.Getenv("BESOM_SBT_MODULE")

se := &ScalaExecutor{
Name: "sbt",
Cmd: cmd,
RunArgs: makeArgs(sbtModule, "run"),
BuildArgs: makeArgs(sbtModule, "compile"),
PluginArgs: append([]string{"-batch", "-error"}, makePluginsSbtCommandParts(sbtModule, bootstrapLibJarPath)),
PluginArgs: []string{"-batch", makePluginsSbtCommandParts(sbtModule, bootstrapLibJarPath, pluginDiscovererOutputPath)},
VersionArgs: []string{"--numeric-version"},
}

return se, nil
}

func makePluginsSbtCommandParts(sbtModule string, bootstrapLibJarPath string) string {
func makePluginsSbtCommandParts(sbtModule string, bootstrapLibJarPath string, pluginDiscovererOutputPath string) string {
if sbtModule != "" {
sbtModule = sbtModule + " / "
}

pluginsSbtCommandParts := []string{
// STDOUT needs to be clean of sbt output, because we expect a JSON with plugin results
`; set outputStrategy := Some(StdoutOutput)`,
fmt.Sprintf(`; set %sCompile / unmanagedJars += Attributed.blank(file("%s"))`, sbtModule, bootstrapLibJarPath),
fmt.Sprintf(`; %srunMain besom.bootstrap.PulumiPluginsDiscoverer`, sbtModule),
fmt.Sprintf(`; %srunMain besom.bootstrap.PulumiPluginsDiscoverer --output-file %s`, sbtModule, pluginDiscovererOutputPath),
}
pluginsSbtCommand := strings.Join(pluginsSbtCommandParts, " ")

Expand All @@ -86,7 +85,7 @@ func makePluginsSbtCommandParts(sbtModule string, bootstrapLibJarPath string) st

func makeArgs(sbtModule string, cmd string) []string {
if sbtModule != "" {
return append([]string{"-batch", fmt.Sprintf("%s/%s", sbtModule, cmd)})
return []string{"-batch", fmt.Sprintf("%s/%s", sbtModule, cmd)}
}
return []string{"-batch", cmd}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,18 @@ func (s scalacli) NewScalaExecutor(opts ScalaExecutorOptions) (*ScalaExecutor, e
if err != nil {
return nil, err
}
return s.newScalaCliExecutor(cmd, opts.BootstrapLibJarPath)
pluginDiscovererOutputPath := PluginDiscovererOutputFilePath(opts.WD)
return s.newScalaCliExecutor(cmd, opts.BootstrapLibJarPath, pluginDiscovererOutputPath)
}

func (scalacli) newScalaCliExecutor(cmd string, bootstrapLibJarPath string) (*ScalaExecutor, error) {
func (scalacli) newScalaCliExecutor(cmd string, bootstrapLibJarPath string, pluginDiscovererOutputPath string) (*ScalaExecutor, error) {
scalaCliOpts := os.Getenv("BESOM_LANGHOST_SCALA_CLI_OPTS")
return &ScalaExecutor{
Name: "scala-cli",
Cmd: cmd,
BuildArgs: []string{"compile", ".", scalaCliOpts},
RunArgs: []string{"run", ".", scalaCliOpts},
PluginArgs: []string{"run", ".", scalaCliOpts, "--jar", bootstrapLibJarPath, "--main-class", "besom.bootstrap.PulumiPluginsDiscoverer"},
PluginArgs: []string{"run", ".", scalaCliOpts, "--jar", bootstrapLibJarPath, "--main-class", "besom.bootstrap.PulumiPluginsDiscoverer", "--", "--output-file", pluginDiscovererOutputPath},
VersionArgs: []string{"version", "--cli", "--offline"},
}, nil
}
16 changes: 14 additions & 2 deletions language-plugin/pulumi-language-scala/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,10 +210,22 @@ func (host *scalaLanguageHost) determinePulumiPackages(
return []plugin.PulumiPluginJSON{}, nil
}

logging.V(5).Infof("GetRequiredPlugins: bootstrap raw output=%v", output)
projectRoot := host.execOptions.WD
outputFilePath := executors.PluginDiscovererOutputFilePath(projectRoot)
defer os.Remove(outputFilePath)

outputFileBytes, err := os.ReadFile(outputFilePath)

if err != nil {
logging.V(3).Infof("language host failed to read project's plugins from file, "+
"returning empty plugins; cause: %s", err)
return []plugin.PulumiPluginJSON{}, nil
}

logging.V(5).Infof("GetRequiredPlugins: bootstrap raw output=%v", string(outputFileBytes))

var plugins []plugin.PulumiPluginJSON
err = json.Unmarshal([]byte(output.stdout), &plugins)
err = json.Unmarshal(outputFileBytes, &plugins)
if err != nil {
if e, ok := err.(*json.SyntaxError); ok {
logging.V(5).Infof("JSON syntax error at byte offset %d", e.Offset)
Expand Down

0 comments on commit ba07512

Please sign in to comment.