Skip to content

Commit

Permalink
Merge pull request #11 from noumenalio/develop
Browse files Browse the repository at this point in the history
Added API docs.
  • Loading branch information
stewartbryson authored Aug 17, 2022
2 parents a6a1140 + 507e771 commit 917f806
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 17 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/gradle-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
- name: Gradle publish
uses: gradle/gradle-build-action@v2
with:
arguments: build publish githubRelease buildDashboard -PgithubToken=${{secrets.GITHUB_TOKEN}}
arguments: build publish groovydoc githubRelease buildDashboard -PgithubToken=${{secrets.GITHUB_TOKEN}}

- name: Upload build reports
uses: actions/upload-artifact@v3
Expand Down
36 changes: 36 additions & 0 deletions plugin/src/main/groovy/io/noumenal/ApplicationContainer.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,62 @@ package io.noumenal

import groovy.util.logging.Slf4j

/**
* A domain container that allows for defining "Snowflake Applications." The plugin automatically creates the UDFs configured in this container.
*/
@Slf4j
class ApplicationContainer {
ApplicationContainer(final String name) {
this.name = name
}
/**
* The name of the domain container.
*/
String name
/**
* The 'inputs' property for the Snowflake UDF.
*/
List inputs
/**
* The 'returns' property for the Snowflake UDF.
*/
String returns
/**
* The 'type' property of the UDF, either 'function' or 'procedure'. DEFAULT: 'function'.
*/
String type = 'function'
/**
* The 'language' property of the UDF, currently only 'JAVA' is supported. DEFAULT: 'JAVA'.
*/
String language = 'JAVA'
/**
* The 'handler' property of the UDF.
*/
String handler

/**
* A getter for the objectType of the UDF.
*
* @return The objectType
*/
String getObjectType() {
returns ? 'function' : 'procedure'
}

/**
* A getter for whether the UDF is a function.
*
* @return Is the UDF a function?
*/
Boolean isFunction() {
objectType == 'function'
}

/**
* A getter for the create statement for the UDF. The imports are passed in as the only property.
*
* @return The complete UDF create statement.
*/
String getCreate(String imports) {
"""|CREATE OR REPLACE $type $name (${inputs.join(', ')})
| returns $returns
Expand Down
49 changes: 48 additions & 1 deletion plugin/src/main/groovy/io/noumenal/SnowflakeExtension.groovy
Original file line number Diff line number Diff line change
@@ -1,34 +1,81 @@
package io.noumenal

import org.gradle.api.Project
/**
* The plugin configuration extension that is applied to the Gradle project as 'snowflake'.
*/
class SnowflakeExtension {
SnowflakeExtension(Project project) {
this.project = project
}
private Project project

/**
* The Snowflake account URL, for instance: https://gradle-snowflake.us-east-1.snowflakecomputing.com:443.
*/
String account
/**
* The Snowflake user to connect as.
*/
String user
/**
* The Snowflake password to connect with.
*/
String password
/**
* The Snowflake database to connect to.
*/
String database
/**
* The Snowflake schema to connect with. Default: 'public'.
*/
String schema = 'public'
/**
* The Snowflake role to connect with.
*/
String role
/**
* The Snowflake warehouse to connect with. Default: 'compute_wh'.
*/
String warehouse = "compute_wh"
/**
* The Snowflake stage to upload to. Default: 'maven'.
*/
String stage = 'maven'
/**
* Optional: specify the URL of {@link #stage} if it is external. The plugin will apply the 'maven-publish' plugin and handle publishing artifacts there.
*/
String publishUrl
/**
* Optional: specify an artifact groupId when using the 'maven-publish' plugin.
*/
String groupId = project.getGroup()
/**
* Optional: specify an artifactId when using the 'maven-publish' plugin.
*/
String artifactId = project.getName()
/**
* Optional: do not automatically apply 'maven-publish' and allow the user to apply that plugin in the 'build.gradle' file.
*/
Boolean useCustomMaven = false

/**
* Convert names to be Snake Case.
*/
private static String toSnakeCase( String text ) {
text.replaceAll( /([A-Z])/, /_$1/ ).toLowerCase().replaceAll( /^_/, '' )
}

/**
* Convert names to be Camel Case.
*/
private static String toCamelCase( String text, boolean capitalized = false ) {
text = text.replaceAll( "(_)([A-Za-z0-9])", { Object[] it -> it[2].toUpperCase() } )
return capitalized ? capitalize(text) : text
}

/**
* Return the name of the Maven publication task associated with the external stage.
*/
String getPublishTask() {
toCamelCase("publish_snowflake_publication_to_${stage}Repository")
}
Expand Down
7 changes: 6 additions & 1 deletion plugin/src/main/groovy/io/noumenal/SnowflakePlugin.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,16 @@ import org.gradle.api.Project
import org.gradle.api.Plugin
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.authentication.aws.AwsImAuthentication

/**
* The Gradle plugin.
*/
@Slf4j
class SnowflakePlugin implements Plugin<Project> {
private static String PLUGIN = 'snowflake'

/**
* Apply the gradle-snowflake plugin to a Gradle project. Also applies the 'com.github.johnrengelman.shadow' and 'java-library' plugins. Supporting the 'scala' plugin instead is on the roadmap.
*/
void apply(Project project) {
project.extensions.create(PLUGIN, SnowflakeExtension)

Expand Down
77 changes: 63 additions & 14 deletions plugin/src/main/groovy/io/noumenal/SnowflakePublish.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ import com.snowflake.snowpark_java.Session
import groovy.util.logging.Slf4j
import net.snowflake.client.jdbc.SnowflakeStatement
import org.gradle.api.DefaultTask
import org.gradle.api.PathValidation
import org.gradle.api.tasks.CacheableTask
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.OutputFile
Expand All @@ -18,84 +16,124 @@ import org.gradle.api.tasks.options.Option
import java.sql.ResultSet
import java.sql.Statement

/**
* A Cacheable Gradle task for publishing Java-based applications as UDFs to Snowflake.
*/
@Slf4j
@CacheableTask
class SnowflakePublish extends DefaultTask {
private static String PLUGIN = 'snowflake'

/**
* A helper for getting the plugin extension.
*
* @return A reference to the plugin extension.
*/
@Internal
def getExtension() {
project.extensions."$PLUGIN"
}

/**
* The task Constructor with 'description' and 'group'.
*
* @return A custom task class.
*/
SnowflakePublish() {
description = "Publish a Java artifact to an external stage and create Snowflake Functions and Procedures."
group = "publishing"
}

/**
* The Snowflake account URL, for instance: https://gradle-snowflake.us-east-1.snowflakecomputing.com:443. Overrides {@link SnowflakeExtension#account}.
*/
@Optional
@Input
@Option(option = "account",
description = "The URL of the Snowflake account."
description = "Override the URL of the Snowflake account."
)
String account = extension.account

/**
* The Snowflake user to connect as. Overrides {@link SnowflakeExtension#user}.
*/
@Optional
@Input
@Option(option = "user",
description = "The user to connect to Snowflake."
description = "Override the Snowflake user to connect as."
)
String user = extension.user

/**
* The Snowflake password to connect with. Overrides {@link SnowflakeExtension#password}.
*/
@Optional
@Input
@Option(option = "password",
description = "The password to connect to Snowflake."
description = "Override the Snowflake password to connect with."
)
String password = extension.password

/**
* The Snowflake database to connect to. Overrides {@link SnowflakeExtension#database}.
*/
@Optional
@Input
@Option(option = "database",
description = "The Snowflake database to use."
description = "Override the Snowflake database to connect to."
)
String database = extension.database

/**
* The Snowflake schema to connect with. Overrides {@link SnowflakeExtension#schema}.
*/
@Input
@Option(option = "schema",
description = "The Snowflake schema to use."
description = "Override the Snowflake schema to connect with."
)
String schema = extension.schema

/**
* The Snowflake role to connect with. Overrides {@link SnowflakeExtension#warehouse}.
*/
@Input
@Option(option = "warehouse",
description = "The Snowflake warehouse to use."
description = "Override the Snowflake role to connect with."
)
String warehouse = extension.warehouse

/**
* The Snowflake warehouse to connect with. Overrides {@link SnowflakeExtension#role}.
*/
@Input
@Option(option = "role",
description = "The Snowflake role to use."
)
String role = extension.role

/**
* The Snowflake stage to upload to. Overrides {@link SnowflakeExtension#stage}.
*/
@Optional
@Input
@Option(option = "stage",
description = "The Snowflake external stage to publish to."
)
String stage = extension.stage

/**
* Optional: manually pass a JAR file path to upload instead of relying on Gradle metadata.
*/
@Optional
@Input
@Option(option = "jar", description = "Manually pass a JAR file path to upload instead of relying on Gradle metadata.")
@Option(option = "jar", description = "Optional: manually pass a JAR file path to upload instead of relying on Gradle metadata.")
String jar = project.tasks.shadowJar.archiveFile.get()

// @InputFile
// def getJarFile() {
// project.file(jar, PathValidation.NONE)
// }

/**
* Create a Snowflake session.
*
* @return a Snowflake session.
*/
@Internal
Session getSession() {
Map props = [
Expand All @@ -121,9 +159,17 @@ class SnowflakePublish extends DefaultTask {
return session
}

/**
* A simple text output file for the Snowflake applications create statements. Mainly for making the class Cacheable.
*/
@OutputFile
File output = project.file("${project.buildDir}/${PLUGIN}/output.txt")

/**
* Get the 'import' property for the UDF.
*
* @return the 'import' property.
*/
String getImports(Session session) {

String basePath = "@${stage}/${extension.groupId.replace('.', '/')}/${extension.artifactId}/${project.version}"
Expand All @@ -150,6 +196,9 @@ class SnowflakePublish extends DefaultTask {
"'$basePath/$fileName'"
}

/**
* The Gradle TaskAction method. Publish the Snowflake Application.
*/
@TaskAction
def publish() {
// keep the session
Expand Down

0 comments on commit 917f806

Please sign in to comment.