What would be the proper gradle way of downloading and unzipping the file from url (http)?
If possible, I'd like to prevent re-downloading each time I run the task (in ant.get can be achieved by skipexisting: 'true').
My current solution would be:
task foo {
ant.get(src: 'http://.../file.zip', dest: 'somedir', skipexisting: 'true')
ant.unzip(src: 'somedir' + '/file.zip', dest: 'unpackdir')
}
still, I'd expect ant-free solution. Any chance to achieve that?
Let's say you want to download this zip file as a dependency:
https://github.com/jmeter-gradle-plugin/jmeter-gradle-plugin/archive/1.0.3.zip
You define your ivy repo as:
repositories {
ivy {
url 'https://github.com/'
patternLayout {
artifact '/[organisation]/[module]/archive/[revision].[ext]'
}
// This is required in Gradle 6.0+ as metadata file (ivy.xml)
// is mandatory. Docs linked below this code section
metadataSources { artifact() }
}
}
reference for required metadata here
The dependency can then be used as:
dependencies {
compile 'jmeter-gradle-plugin:jmeter-gradle-plugin:1.0.3#zip'
//This maps to the pattern: [organisation]:[module]:[revision]:[classifier]#[ext]
}
To unzip:
task unzip(type: Copy) {
def zipPath = project.configurations.compile.find {it.name.startsWith("jmeter") }
println zipPath
def zipFile = file(zipPath)
def outputDir = file("${buildDir}/unpacked/dist")
from zipTree(zipFile)
into outputDir
}
optional:
If you have more than one repository in your project, it may also help (for build time and somewhat security) to restrict dependency search with relevant repositories.
Gradle 6.2+:
repositories {
mavenCentral()
def github = ivy {
url 'https://github.com/'
patternLayout {
artifact '/[organisation]/[module]/archive/[revision].[ext]'
}
metadataSources { artifact() }
}
exclusiveContent {
forRepositories(github)
filter { includeGroup("jmeter-gradle-plugin") }
}
}
Earlier gradle versions:
repositories {
mavenCentral {
content { excludeGroup("jmeter-gradle-plugin") }
}
ivy {
url 'https://github.com/'
patternLayout {
artifact '/[organisation]/[module]/archive/[revision].[ext]'
}
metadataSources { artifact() }
content { includeGroup("jmeter-gradle-plugin") }
}
}
plugins {
id 'de.undercouch.download' version '4.0.0'
}
/**
* The following two tasks download a ZIP file and extract its
* contents to the build directory
*/
task downloadZipFile(type: Download) {
src 'https://github.com/gradle-download-task/archive/1.0.zip'
dest new File(buildDir, '1.0.zip')
}
task downloadAndUnzipFile(dependsOn: downloadZipFile, type: Copy) {
from zipTree(downloadZipFile.dest)
into buildDir
}
https://github.com/michel-kraemer/gradle-download-task
There isn't currently a Gradle API for downloading from a URL. You can implement this using Ant, Groovy, or, if you do want to benefit from Gradle's dependency resolution/caching features, by pretending it's an Ivy repository with a custom artifact URL. The unzipping can be done in the usual Gradle way (copy method or Copy task).
Unzipping using the copy task works like this:
task unzip(type: Copy) {
def zipFile = file('src/dists/dist.zip')
def outputDir = file("${buildDir}/unpacked/dist")
from zipTree(zipFile)
into outputDir
}
http://mrhaki.blogspot.de/2012/06/gradle-goodness-unpacking-archive.html
This works with Gradle 5 (tested with 5.5.1):
task download {
doLast {
def f = new File('file_path')
new URL('url').withInputStream{ i -> f.withOutputStream{ it << i }}
}
}
Calling gradle download downloads the file from url to file_path.
You can use the other methods from other answers to unzip the file if necessary.
I got #RaGe's answer working, but I had to adapt it since the ivy layout method has been depreciated see
https://docs.gradle.org/current/dsl/org.gradle.api.artifacts.repositories.IvyArtifactRepository.html#org.gradle.api.artifacts.repositories.IvyArtifactRepository:layout(java.lang.String,%20groovy.lang.Closure)
So to get it working I had to adjust it to this for a tomcat keycloak adapter:
ivy {
url 'https://downloads.jboss.org/'
patternLayout {
artifact '/[organization]/[revision]/adapters/keycloak-oidc/[module]-[revision].[ext]'
}
}
dependencies {
// https://downloads.jboss.org/keycloak/4.8.3.Final/adapters/keycloak-oidc/keycloak-tomcat8-adapter-dist-4.8.3.Final.zip
compile "keycloak:keycloak-tomcat8-adapter-dist:$project.ext.keycloakAdapterVersion#zip"
}
task unzipKeycloak(type: Copy) {
def zipPath = project.configurations.compile.find {it.name.startsWith("keycloak") }
println zipPath
def zipFile = file(zipPath)
def outputDir = file("${buildDir}/tomcat/lib")
from zipTree(zipFile)
into outputDir
}
"native gradle", only the download part (see other answers for unzipping)
task foo {
def src = 'http://example.com/file.zip'
def destdir = 'somedir'
def destfile = "$destdir/file.zip"
doLast {
def url = new URL(src)
def f = new File(destfile)
if (f.exists()) {
println "file $destfile already exists, skipping download"
} else {
mkdir "$destdir"
println "Downloading $destfile from $url..."
url.withInputStream { i -> f.withOutputStream { it << i } }
}
}
}
Related
In Deno it is possible to version the dependencies in the import statement, and there's no package.json like with npm.
But how to managed it's URLs and versions in a single place?
I will have multiple files and dependencies that will be declared all over my system.
For example:
dateUtils.ts
import { parseDate } from 'https://deno.land/std#0.50.0/datetime/mod.ts';
const DEFAULT_MASK = "dd-mm-yyyy";
export function parse(date: string): Date {
return parseDate(date, DEFAULT_MASK);
};
service.ts
import { v4 } from "https://deno.land/std/uuid/mod.ts";
export function process(request: any) {
const { token } = request;
const isValid = v4.validate(token);
console.log(`Token validity: ${isValid}`)
};
app.ts
import { parse } from "./dateUtil.ts";
import * as service from "./service.ts";
const date = parse("20-05-2020");
console.log(date);
const request = {
token: "408d30e5-1e90-45e3-b299-6520feee6d76"
}
service.process(request)
To avoid typing https://deno.land/std/uuid/mod.ts everywhere you can use import maps
// import_map.json
{
"imports": {
"http/": "https://deno.land/std/http/"
}
}
// server.ts
import { serve } from "http/server.ts";
const body = new TextEncoder().encode("Hello World\n");
for await (const req of serve(":8000")) {
req.respond({ body });
}
deno run --importmap=import_map.json --allow-net server.ts
import maps are currently unstable, but you can use them behind --unstable flag.
Aside from that it's common to have a deps.ts file where you'll re-export all your dependencies.
// deps.ts
export * as path from "https://deno.land/std#0.51.0/path/mod.ts";
// other exports .. from
// some other file
import { path } from './deps.ts' // instead of "https://deno.land/std#0.51.0/path/mod.ts"
path.basename('/bar/test.txt');
In deno there is a convention for consolidating imports into deps.ts.
export { parseDate } from 'https://deno.land/std#0.50.0/datetime/mod.ts';
export { v4 } from "https://deno.land/std/uuid/mod.ts";
Exports can then be imported in other modules/scripts on your application:
import { v4 } from "./deps.ts";
import { parseDate } from './deps.ts';
const myUUID = v4.generate();
parseDate("20-05-2020", "dd-mm-yyyy")
When using this approach one should consider integrity checking & lock files:
// Add a new dependency to "src/deps.ts", used somewhere else.
export { xyz } from "https://unpkg.com/xyz-lib#v0.9.0/lib.ts";
# Create/update the lock file "lock.json".
deno cache --lock=lock.json --lock-write src/deps.ts
# Include it when committing to source control.
git add -u lock.json
git commit -m "feat: Add support for xyz using xyz-lib"
git push
So I have a spring boot project that is using freemarker and is built using gradle.
This is my build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:2.1.9.RELEASE")
}
}
plugins {
id 'org.springframework.boot' version '2.1.9.RELEASE'
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
id 'java'
id 'application'
}
group = 'some.project'
version = '4'
mainClassName = "some.project.Application"
repositories {
mavenCentral()
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-web") {
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
}
compile('org.springframework.boot:spring-boot-starter-data-jpa') {
exclude group: 'org.apache.tomcat', module: 'tomcat-jdbc'
}
implementation 'org.springframework.boot:spring-boot-starter-jetty'
implementation 'org.springframework.boot:spring-boot-starter-freemarker'
}
jar {
// include all the jars
from {
(configurations.runtime).collect {
it.isDirectory() ? it : zipTree(it)
}
}
manifest {
attributes 'Main-Class': 'some.project.Application'
}
}
I have decided to start using scss because my css files were becoming a little difficult to manage and keep consistent. However I can't seem to figure out how to get my application to load up scss files. All the scss files are located in resources/static/scss, what should I do with them so that they become css and readable by my spring boot application and freemarker?
I have this as settings.gradle
buildscript {
repositories {
maven {
url 'https://plugins.gradle.org/m2/'
}
}
dependencies {
classpath 'gradle.plugin.net.vivin:gradle-semantic-build-versioning:4.0.0'
}
}
apply plugin: 'net.vivin.gradle-semantic-build-versioning'
I need to convert it to a settings.gradle.kts kotlin DSL file. I tried:
buildscript {
repositories {
maven {
url = uri("https://plugins.gradle.org/m2/")
}
}
dependencies {
classpath("gradle.plugin.net.vivin:gradle-semantic-build-versioning:4.0.0")
}
}
apply ("gradle.plugin.net.vivin.gradle-semantic-build-versioning")
This gives the error:
Cannot apply plugin of class 'org.gradle.api.Plugin' to
'net.vivin.gradle-semantic-build-versioning' (class: java.lang.String)
as it does not implement PluginAware
What is the problem here?
The solution is:
plugins.apply("net.vivin.gradle-semantic-build-versioning")
The problem:
I have a jar in some repository.
I want to run the jar and do something with it during gradle task.
The attempt:
apply plugin: 'java'
repositories {
maven {
url "<<<valid repo url>>>"
}
mavenCentral()
}
dependencies {
compile(group: 'com.google.developers', name: 'compiler', version: 'v20150315', ext: 'pom')
}
task doTheJar {
dependsOn configurations.compile
exec {
executable "sh"
args "-c","java -jar <<the-artifact>> smoething something"
}
}
Is there a way to do it?
Is there a way to do it without java plugin?
Thanks.
It will be better to do it in the following way:
apply plugin: 'java'
repositories {
maven {
url "<<<valid repo url>>>"
}
mavenCentral()
}
configurations {
runjar
}
dependencies {
runjar 'some:artifact:1.0'
}
task runTheJar(type: JavaExec) {
main 'main.class.to.be.run'
classpath configurations.runjar
args 's1', 's2', 's3'
}
I have two task nativeJar and native64Jar, manifest and doLast closers are same for both the tasks except the file names. So is It possible to extract that code in a common method and pass two file names as a method parameter and call that common method from both tasks or call that method from dolast clouser.
task nativeJar( type: Jar ) {
doFirst {
delete fileTree(dir: "$releaseDir", include: "*.jar")
}
baseName = 'NativeLibs'
destinationDir = new File(releaseDir)
from files(releaseDir + 'jar_merge/signedNativeLibs')
manifest {
attributes 'Permissions' : 'all-permissions', 'Publisher' : 'abc', 'Application-Name' : 'WorkBench', 'Codebase' : '*.abc.com'
}
doLast {
ant.signjar( jar: "$releaseDir/NativeLibs.jar", alias:"WorkBench", keystore: "WorkBench.jks", signedjar: "$releaseDir/signedNativeLibs.jar", storepass: "freddie" )
}
}
// Create signedNativeLibs64.jar file
task native64Jar( type: Jar , dependsOn: 'nativeJar' ) {
baseName = 'NativeLibs64'
destinationDir = new File(releaseDir)
from files(releaseDir + 'jar_merge/signedNativeLibs64')
manifest {
attributes 'Permissions' : 'all-permissions', 'Publisher' : 'abc', 'Application-Name' : 'WorkBench', 'Codebase' : '*.abc.com'
}
doLast {
ant.signjar( jar: "$releaseDir/NativeLibs64.jar", alias:"WorkBench", keystore: "WorkBench.jks", signedjar: "$releaseDir/signedNativeLibs64.jar", storepass: "freddie" )
}
}
I would recommend splitting out the signing as a separate task so that you get proper up-to-date checks from Gradle. As you have it now, you'll always sign the jar every time you build. And if you delete the signed jar, it won't generate again until you clean the native jar too.
You can share configuration closures between tasks. E.g.,
[ task1, task2 ].each { task ->
task.configure {
// shared closure
}
}
There are a few other best practices I'd follow.
Don't use new File() since it makes your script dependent on the current working directory.
Refer to outputs via the task versus recreating the full path (e.g., what you're doing with $releaseDir/NativeLibs.jar). Gradle is able to infer dependencies that way.
Use a custom task class vs an ad-hoc task with doFirst()/doLast(). Since you're delegating all the work to the ant task, this should be really simple.
I'm not sure why you need your particular file names, but I left them as-is. If they're not important, removing them would make this even simpler.
I took a stab at your example (disclaimer: I didn't try it):
task nativeJar( type: Jar ) {
baseName = 'NativeLibs'
from files(releaseDir + 'jar_merge/signedNativeLibs')
}
task native64Jar( type: Jar ) {
baseName = 'NativeLibs64'
from files(releaseDir + 'jar_merge/signedNativeLibs64')
}
[ nativeJar, native64Jar ].each { task ->
task.configure {
destinationDir = file(releaseDir)
manifest {
attributes 'Permissions' : 'all-permissions', 'Publisher' : 'Financial Engineering', 'Application-Name' : 'WorkBench', 'Codebase' : '*.fhlmc.com'
}
}
}
// this class definition should go at the top of your build.gradle script else it will through an exception mentioned in comments
class SignJarTask extends DefaultTask {
#InputFile File inputFile
#OutputFile File outputFile
#TaskAction
void signJar() {
ant.signjar( jar: inputFile, alias:"WorkBench", keystore: "WorkBench.jks", signedjar: outputFile, storepass: "freddie" )
}
}
task signJar(type: SignJarTask) {
inputFile = file("$releaseDir/NativeLibs.jar")
outputFile = file("$releaseDir/signedNativeLibs.jar")
}
task sign64Jar(type: SignJarTask) {
inputFile = file("$releaseDir/NativeLibs64.jar")
outputFile = file("$releaseDir/signedNativeLibs64.jar")
}