Skip to content
This repository has been archived by the owner on Dec 5, 2024. It is now read-only.

Commit

Permalink
Add paket-unity UPM mode [ATLAS-1273] (#96)
Browse files Browse the repository at this point in the history
  • Loading branch information
Joaquimmnetto authored Jul 27, 2023
1 parent bfd797f commit 79d4391
Show file tree
Hide file tree
Showing 12 changed files with 353 additions and 18 deletions.
2 changes: 1 addition & 1 deletion Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ withCredentials([usernameColonPassword(credentialsId: 'artifactory_publish', var
"nugetkey=${artifactory_deploy}"
]

buildGradlePlugin platforms: ['macos','windows','linux'], sonarToken: sonar_token, testEnvironment: testEnvironment
buildGradlePlugin platforms: ['macos','windows'/*,'linux'*/], sonarToken: sonar_token, testEnvironment: testEnvironment
}
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,6 @@ dependencies {
testImplementation('org.apache.commons:commons-lang3:3.12.0')
testImplementation 'org.apache.httpcomponents:httpclient:[4.5.13,5)'
implementation('com.google.guava:guava:19.0')
implementation 'com.wooga.gradle:gradle-commons:[1,2['
testImplementation 'com.wooga.gradle:gradle-commons-test:[1,2['
}
43 changes: 39 additions & 4 deletions docs/Unity.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,45 @@ Tasks

The `paket-unity` plugin adds a few tasks that will hook themself onto `paket-get`

| Task name | Depends on | Type | Description |
| ------------------- | ------------------- | --------------------------------------------------- | ----------- |
| paketUnityInstall | | `wooga.gradle.paket.unity.tasks.PaketUnityInstall` | Installs the dependencies into the Unity3d project
| Task name | Depends on | Type | Description |
|-------------------|------------|----------------------------------------------------|----------------------------------------------------|
| paketUnityInstall | | `wooga.gradle.paket.unity.tasks.PaketUnityInstall` | Installs the dependencies into the Unity3d project |

The `paketUnityInstall` will configure itself as a [`finalizedBy`][gradle_finalizedBy] task for `paketInstall`, `paketRestore` and `paketUpdate`. There is no need to call this task manually. The task also gets skipped when no `paket.unity3d.references` file can be found anywhere in the project directory tree.
The `paketUnityInstall` will configure itself as a [`finalizedBy`][gradle_finalizedBy] task
for `paketInstall`, `paketRestore` and `paketUpdate`. There is no need to call this task manually. The task also gets
skipped when no `paket.unity3d.references` file can be found anywhere in the project directory tree.


Extension
---------

The `paketUnity` extension provided by the plugin can be used for configuration. It has all properties
from `PaketPluginExtension`, plus the ones below:

| Property | Type | Description |
|--------------------------------|-----------------------------------------|-------------------------------------------------------------------------------------------------|
| paketReferenceFiles | `FileCollection` (Read only) | A list of all `paket.unity3D.references` files |
| paketOutputDirectoryName | `String` | Output directory for the paket installation. Relative to `<unity_project>/Assets`. |
| assemblyDefinitionFileStrategy | `AssemblyDefinitionFileStrategy` (Enum) | Strategy regarding assemble definition files. |
| includeAssemblyDefinitions | `Boolean` | Whether assembly definition files should be included during installation. |
| paketUpmPackageEnabled | `Property<Boolean>` | Enables/Disables UPM package mode. |
| paketUpmPackageManifests | `MapProperty<String, Map>` | Maps `[paketName: upmPackageManifestMap]` for package.json files generated in UPM package mode. |


UPM mode
--------

Paket packages can also be configured to be installed as UPM packages. This can be useful when your paket package
contains an UPM one (with a `package.json` file).
This mode sets the installation directory (`paketOutputDirectoryName`) to the unity project's `Packages` folder, and
ensures that the `package.json`
file for each dependency is in the installed package root.

If an installed package is not UPM-compatible, that is, it doesn't have a `package.json` file, such file will be created.
By default, a `package.json` is generated with `com.wooga.nuget.${paketPackage.toLowerCase()}` name, and version `0.0.0`,
but those can be overridden and more properties can be added on using the mappings in `paketUpmPacakgeJson`.

UPM mode can be enabled through the `paketUpmPackageEnabled` property, or using the `paketUnity.enablePaketUpmPackages()` extension
method. It is disabled by default.

[gradle_finalizedBy]: https://docs.gradle.org/3.5/dsl/org.gradle.api.Task.html#org.gradle.api.Task:finalizedBy
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,18 @@

package wooga.gradle.paket.unity

import com.wooga.gradle.test.PropertyUtils
import groovy.json.JsonSlurper
import nebula.test.IntegrationSpec
import nebula.test.functional.ExecutionResult
import spock.lang.Shared
import spock.lang.Unroll
import wooga.gradle.extensions.PaketDependencyInterceptor
import wooga.gradle.paket.get.PaketGetPlugin
import wooga.gradle.paket.unity.fixtures.PaketFixturesTrait
import wooga.gradle.paket.unity.tasks.PaketUnityInstall
import wooga.gradle.paket.unity.tasks.PaketUnwrapUPMPackages

class PaketUnityIntegrationSpec extends IntegrationSpec {
class PaketUnityIntegrationSpec extends IntegrationSpec implements PaketFixturesTrait {

def setup() {
buildFile << """
Expand Down Expand Up @@ -237,9 +239,9 @@ class PaketUnityIntegrationSpec extends IntegrationSpec {
includeAssemblyDefinitions == outputAsmdefFile.exists()

where:
baseConfigurationString | includeAssemblyDefinitions
"paketUnity" | true
"paketUnity" | false
baseConfigurationString | includeAssemblyDefinitions
"paketUnity" | true
"paketUnity" | false
"project.tasks.getByName(#taskName%%)" | true
"project.tasks.getByName(#taskName%%)" | false

Expand All @@ -249,6 +251,79 @@ class PaketUnityIntegrationSpec extends IntegrationSpec {
configurationString = baseConfigurationString.replace("#taskName%%", "'${taskName}'")
}

def "ensures Paket-installed UPM packages have the package dot json in the package root"() {
given:
def unityProjDir = new File(projectDir, "unity")
new File(unityProjDir, "Assets").mkdirs()
def (_, testPkgJson) = fakeUPMPaketPackage("test", unityProjDir)
def pkgInstallDir = new File(unityProjDir, "Packages/test")
def testPkgContents = testPkgJson.text

and:
buildFile << """
paketUnity {
enablePaketUpmPackages()
}
"""

when:
def result = runTasks(PaketUnityPlugin.INSTALL_TASK_NAME)

then:
result.success
def pkgJsonFile = new File(pkgInstallDir, "package.json")
pkgJsonFile.file
pkgJsonFile.text == testPkgContents
}

def "ensures Paket-installed non-UPM packages #msg a generated package dot json in package root when paketUpmPackageEnabled is #paketUpmPackageEnabled"() {
given:
def unityProjDir = new File(projectDir, "unity")
new File(unityProjDir, "Assets").mkdirs()
def testNuGetPackage = fakePaketPackage("test")
def manifestJson = new File(unityProjDir, "Packages/manifest.json").with {
mkdirs(); createNewFile();
it
}
def pktUnityInstallDir = new File(unityProjDir, "Packages/test")
assert !new File(testNuGetPackage, "package.json").exists()

and:
buildFile << """
paketUnity {
paketUpmPackageEnabled = $paketUpmPackageEnabled
${overrides ?
"paketUpmPackageManifests = ['test': ${PropertyUtils.wrapValueBasedOnType(overrides, Map)}]" :
""
}
}
"""

when:
def result = runTasks(PaketUnityPlugin.INSTALL_TASK_NAME)

then:
result.success
def pkgJsonFile = new File(pktUnityInstallDir, "package.json")
if (hasPackageManifest) {
pkgJsonFile.file
manifestJson.file
def pkgJson = new JsonSlurper().parse(pkgJsonFile) as Map<String, Object>
pkgJson['name'] == (overrides?.get('name') ?: "com.wooga.nuget.${pktUnityInstallDir.name.toLowerCase()}")
pkgJson.entrySet().containsAll(overrides?.entrySet() ?: [:])
} else {
!pkgJsonFile.file
!manifestJson.file
}

where:
paketUpmPackageEnabled | hasPackageManifest | overrides | msg
true | true | null | "has"
true | true | [name: "com.custom.name"] | "has"
true | true | [custom: "customfield"] | "has"
false | false | null | "hasn't"
}

private void setupPaketProject(dependencyName, unityProjectName) {

def dependencies = createFile("paket.dependencies")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package wooga.gradle.paket.unity.fixtures

import nebula.test.IntegrationSpec

import java.nio.file.FileSystems
import java.nio.file.Files
import java.nio.file.Path
import java.util.stream.Collectors

class PaketFixtures implements PaketFixturesTrait {

private IntegrationSpec spec

PaketFixtures(IntegrationSpec spec) {
this.spec = spec
}

@Override
File getProjectDir() {
return spec.projectDir
}
}

trait PaketFixturesTrait {
abstract File getProjectDir()

File fakePaketPackage(String name,
File baseDir = projectDir,
File installedPackagesDir = new File(projectDir, "packages"),
File unityDir = new File(projectDir, "unity")) {
def dependencies = new File(projectDir, "paket.dependencies")
dependencies << """
source https://nuget.org/api/v2
nuget ${name}
""".stripIndent()

def lockFile = new File(projectDir, "paket.lock")
lockFile << """${name}""".stripIndent().trim()

def referencesFile = new File(unityDir, "paket.unity3d.references")
referencesFile.parentFile.mkdirs()
referencesFile << "\n${name}".stripIndent().trim()

def packageFolder = new File(installedPackagesDir, "$name")
packageFolder.mkdirs()
packageFolder.with {
new File(it, "content/innerFolder").mkdirs()
new File(it, "content/innerFolder/something.cs") << "CONTENT"
}
return packageFolder
}

Tuple2<File, File> fakeUPMPaketPackage(String name,
File unityDir = new File(projectDir, "unity"),
File installedPackagesDir = new File(projectDir, "packages"),
File baseDir = projectDir) {
def packageFolder = fakePaketPackage(name, baseDir, installedPackagesDir, unityDir)
createMetafiles(packageFolder)
new File(packageFolder, "content/innerFolder/package.json") << """{"name" : "com.something.${name.toLowerCase()}"}"""
new File(packageFolder, "content/innerFolder/package.json.meta") << "META"
return [packageFolder, new File(packageFolder, "content/innerFolder/package.json")]
}

List<File> createMetafiles(File baseFolder) {
def metaCandidates = Files.walk(baseFolder.toPath()).map {it.toFile() }
.filter { it != baseFolder }
.filter {!it.name.endsWith(".meta") }

def createdMetas = metaCandidates.map { new File(it.parentFile, "${it.name}.meta") }
.filter {!it.exists() }
.map {it << "META" }
.collect(Collectors.toList())

return createdMetas
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,13 @@

package wooga.gradle.paket.unity

import org.gradle.api.Action

import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.file.CopySpec
import wooga.gradle.paket.base.PaketBasePlugin
import wooga.gradle.paket.base.PaketPluginExtension
import wooga.gradle.paket.get.PaketGetPlugin
import wooga.gradle.paket.get.tasks.PaketUpdate
import wooga.gradle.paket.unity.internal.AssemblyDefinitionFileStrategy
import wooga.gradle.paket.unity.internal.DefaultPaketUnityPluginExtension
import wooga.gradle.paket.unity.tasks.PaketUnityInstall
import wooga.gradle.paket.unity.tasks.PaketUnwrapUPMPackages
Expand Down Expand Up @@ -61,6 +59,7 @@ class PaketUnityPlugin implements Plugin<Project> {
createPaketUnityInstallTasks(project, extension)
createPaketUpmUnwrapTasks(project, extension)
extension.assemblyDefinitionFileStrategy = PaketUnityPluginConventions.assemblyDefinitionFileStrategy
extension.paketUpmPackageEnabled.convention(PaketUnityPluginConventions.paketUpmPackageEnabled)

project.tasks.matching({ it.name.startsWith("paketUnity")}).configureEach { task ->
task.onlyIf {
Expand All @@ -86,6 +85,8 @@ class PaketUnityPlugin implements Plugin<Project> {
t.frameworks = extension.getPaketDependencies().getFrameworks()
t.lockFile = extension.getPaketLockFile()
t.referencesFile = referenceFile
t.paketUpmPackageEnabled.convention(extension.paketUpmPackageEnabled)
t.paketUpmPackageManifests.convention(extension.paketUpmPackageManifests)
}
return installProvider
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ import wooga.gradle.paket.unity.internal.AssemblyDefinitionFileStrategy

class PaketUnityPluginConventions {
static final AssemblyDefinitionFileStrategy assemblyDefinitionFileStrategy = AssemblyDefinitionFileStrategy.disabled
static final boolean paketUpmPackageEnabled = false
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import wooga.gradle.paket.unity.internal.AssemblyDefinitionFileStrategy
/**
* A extensions point for paket unity
*/
interface PaketUnityPluginExtension extends PaketPluginExtension {
interface PaketUnityPluginExtension extends PaketPluginExtension, PaketUpmPackageSpec {

/**
* Returns a {@link FileCollection} object containing all {@code paket.unity3D.references} files.
Expand All @@ -34,7 +34,7 @@ interface PaketUnityPluginExtension extends PaketPluginExtension {
FileCollection getPaketReferencesFiles()

/**
* @return the paket unity output directory name
* @return the paket unity output directory name. Relative to `<unity_project>/Assets`
*/
String getPaketOutputDirectoryName()

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package wooga.gradle.paket.unity

import com.wooga.gradle.BaseSpec
import org.gradle.api.provider.MapProperty
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Optional

trait PaketUpmPackageSpec implements BaseSpec {

private final MapProperty<String, Map<String, Object>> paketUpmPackageManifests = objects.mapProperty(String, Map)

/**
* Map [<paket_package_name>: <upm_manifest_contents>] that overrides the contents of generated package.json files in UPM package mode.
*/
@Input
@Optional
MapProperty<String, Map<String, Object>> getPaketUpmPackageManifests() {
return paketUpmPackageManifests
}

void setPaketUpmPackageManifests(Map paketUpmPackages) {
this.paketUpmPackageManifests.set(paketUpmPackages)
}

void setPaketUpmPackageManifests(Provider<Map<String, String>> paketUpmPackages) {
this.paketUpmPackageManifests.set(paketUpmPackages)
}


private final Property<Boolean> paketUpmPackageEnabled = objects.property(Boolean)

/**
*
* Enables "UPM package mode" for paket. This mode searches for a folder with a 'package.json' in the paket project,
* and installs the package in the 'Packages' folder, using the discovered folder as root.
* <br>
* Non-UPM compatible packages will be given a basic package.json file with a package name described in the
* {@code paketUpmPackages} property. If a mapping is not found there,
* a generic 'com.wooga.nuget.<paket-package-name>' name will be used.
* <br>
*/
void enablePaketUpmPackages() {
paketUpmPackageEnabled.set(true)
}

/**
* Enables/Disables "UPM package mode" for paket. See {@code PaketUpmPackageSpec::enablePaketUpmPackages} for more details.
*/
@Input
@Optional
Property<Boolean> getPaketUpmPackageEnabled() {
return paketUpmPackageEnabled
}

Property<Boolean> isPaketUpmPackageEnabled() {
return paketUpmPackageEnabled
}

void setPaketUpmPackageEnabled(Boolean enablePaketUpmPackages) {
this.paketUpmPackageEnabled.set(enablePaketUpmPackages)
}

void setPaketUpmPackageEnabled(Provider<Boolean> enablePaketUpmPackages) {
this.paketUpmPackageEnabled.set(enablePaketUpmPackages)
}
}
Loading

0 comments on commit 79d4391

Please sign in to comment.