I have an Android-Library that I would like to publish on bintray.
So far so good, I am using the gradle-bintray-plugin 1.2 with the following configuration:
bintray {
user = properties.getProperty("bintray.user")
key = properties.getProperty("bintray.apikey")
configurations = ['archives']
pkg {
repo = "android" // thats how my maven repository is called on bintray
name = "mylibrary"
websiteUrl = "https://somewebsite" // replaced this, since the project should not matter
issueTrackerUrl = 'some issuetracker url'
vcsUrl = "some repository"
licenses = ["Apache-2.0"]
publish = true
version {
// the 2 functions here, are building the version number
name = versionNameBuild() // i.e. 1.0.0-SomeName
vcsTag = versionName() // 1.0.0
gpg {
// keys are uploaded
sign = true
}
}
}
}
The first issue I ran into, was that after I uploaded the library the Version number was "unspecified". Meaning, that the file was uploaded successfully, but it was called smth. like "mylibrary-unspecified.aar". I figured out that I had to additionally specify the project version number in gradle.
like this:
project.version = "1.0.1"
After that, this was working fine. Now I have only 2 Questions left:
I would expect my files to be uploaded like this:
$BINTRAYUSERNAME/$REPONAME/$PACKAGENAME/$VERSION/*.aar
But they are actually uploaded to smth like this:
$BINTRAYUSERNAME/$REPONAME/$PROJECT_FOLDERNAME_OF_ANDROID_STUDIO/$SUBDIRECTORY_OF_THE_LIBRARY/$VERSION/*.aar
Can I change this "path" somehow? Does it matter?
Which leads me to my next question.
How can I specify the maven group-type? I mean it's a maven repository right? So I should be able to set this up? Is this may be related to my first question?
Can I change this "path" somehow? Does it matter?
Yes and yes. This path changed, as soon as I used the group variable:
group = "my.awesome.group"
This solves the second Question as well. The path of the uploaded file is then:
$BINTRAYUSERNAME/$REPONAME/$PACKAGENAME/$GROUPPATH/$VERSION/*.aar
I recommend using for Android libraries the example script.
Related
When trying to upload my application (aab) to the play store - Im seeing this error, and I cant find anyone talking about it. The error message is translated from Swedish -> English using Google Translate.
The versions used are 0, and 12451000. Its clear to me that the 0 is a mistake, but Ive now spent several days trying to figure out where the 0 is coming from without any success.
Things Ive tried;
Export the aab using different versions of Android Studio. Ive tried stable, beta & canary.
Reduce versions of my dependencies to the ones I know have worked in the past.
Update dependencies, gradle, libraries, etc.
Invalidate caches, reinstall Android Studio, wipe its settings and follow its 'repair IDE' wizard.
Verify that build.gradle and plugins are written & used correctly.
My usage of the play services is quite broad, I apply them in my app/phone module with an additional line in my plugins block id 'com.google.gms.google-services'. The root build.gradle contains the classpath to com.google.gms:google-services.
My full related dependencies are as follows (declared in TOML);
firebase-gradle = { module = 'com.google.firebase:firebase-crashlytics-gradle', version = '2.8.1' }
firebase-bom = { module = 'com.google.firebase:firebase-bom', version = '29.3.0' }
firebase-crashlytics = { module = 'com.google.firebase:firebase-crashlytics-ktx' }
firebase-auth = { module = 'com.google.firebase:firebase-auth-ktx' }
firebase-database = { module = 'com.google.firebase:firebase-database-ktx' }
google-gradle = { module = 'com.google.gms:google-services', version.ref = 'google-services' }
google-auth = { module = 'com.google.android.gms:play-services-auth', version.ref = 'google-auth' }
google-fitness = { module = 'com.google.android.gms:play-services-fitness', version.ref = 'google-fitness' }
google-services = '4.3.10'
google-auth = '20.1.0'
google-fitness = '21.0.1'
At this point Im looking for any guidance I can get. Are there any additional troubleshooting steps I can take? Have you experienced something similar in the past? Please let me know.
This could be a versioning problem. Try changing the
com.android.application and com.android.library
versions from 7.3.0-alpha 07 to 7.1.2.
Alternatively, try the remedy below
androidComponents {
onVariants(selector().all(), {
def capitalizedVariantName = name.substring(0,1).toUpperCase() + name.substring(1)
afterEvaluate {
tasks.named("map${capitalizedVariantName}SourceSetPaths").configure {
it.dependsOn("process${capitalizedVariantName}GoogleServices")
}
}
})
}
The issue has been fixed and closed. Check it here on Issue Tracker
The work around could be unnecessary.
I have been using GitHub packages for a while, in an Android project, without having any issue.
Now when I try to publish a new package I get the error:
Could not PUT Received status code 422 from server: Unprocessable Entity
To be sure that I hadn't change anything I went back to a git-tag from which I successfully managed to publish a package a few days ago, I changed only the version to generate a different package. I get the same error.
I added logs and I can see that the token is read correctly, all the value (GROUP, VERSION, etc) seem correct and that the file that I'm trying to publish is there in the correct folder.
I have also tried to create and use a new token in case something was wrong with the old one but it didn't help.
Would GitHub reject the publishing with that error in case I published too many files? I did not find any documentation about the error that you get in that case.
EDIT
I have also tried to create a new project and post to that one, in case something had got messed up in the initial one, but it did not work either.
I have tried to PUT a file directly using CURL and this worked that means that the token is correct and that the problem is not the limit in the total size of the published packages:
curl -X PUT \
"https://maven.pkg.github.com/companyname/repositoryname/com/companyname/artifactid/v2.1.520/artifactid-v2.1.520.aar" \
-H "Authorization: token mytoken” \
--upload-file “/full/path/to/file.aar" -vvv
Of course, this is not the solutions since I need to post the maven repo with the pom etc.
END EDIT
Here my configuration that had been working for a long time and that is just following the documentation + the logs that I added to investigate the issue.
In the build.gradle:
allprojects {
repositories {
google()
jcenter()
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/companyname/companyname-android-sdk")
credentials {
username = project.findProperty("gpr.user") ?: System.getenv("GitHubPackagesUsername")
password = project.findProperty("gpr.key") ?: System.getenv("GitHubPackagesToken")
println "GitHubPackages build.gradle\n\tusername=$username\n\ttoken=$password"
}
}
}
}
in the publish-artifacts.gradle:
publishing {
repositories {
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/companyname/companyname-android-sdk")
credentials {
username = project.findProperty("gpr.user") ?: System.getenv("GitHubPackagesUsername")
password = project.findProperty("gpr.key") ?: System.getenv("GitHubPackagesToken")
println "GitHubPackages Publish Artifact:\n\tusername=$username\n\ttoken=$password"
}
}
}
publications {
gpr(MavenPublication) {
println "\tskSdkVersion=$SK_SDK_VERSION\n\tarchivesBaseName=$archivesBaseName\n\tGROUP=$GROUP\n\tdesciption=$POM_DESCRIPTION"
println "artifact from $buildDir/outputs/aar/$archivesBaseName-${VARIANT_SUFFIX}.aar"
groupId SK_GROUP
version SK_SDK_VERSION
artifactId archivesBaseName
artifact "$buildDir/outputs/aar/$archivesBaseName-${VARIANT_SUFFIX}.aar"
description POM_DESCRIPTION
pom.packaging POM_PACKAGING
pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
configurations.implementation.allDependencies.each {
println "dependency=$it"
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', it.group)
dependencyNode.appendNode('artifactId', it.name)
dependencyNode.appendNode('version', it.version)
}
}
}
}
}
in the gradle.properties file:
POM_NAME=PackageName
POM_PACKAGING=aar
GROUP=com.companyname
POM_DESCRIPTION=CompanyName SDK Core library
VARIANT_SUFFIX is set from an env variable.
archivesBaseName is set in the module's build.gradle
Could you try lower casing your artifact ID?
I was facing the same issue and lowercasing it made it work.
Reference: https://github.community/t/gradle-maven-deploy-failing-with-422-unprocessable-entity/137299/3
In my case when the artifact had the name api or service or serde it was being blocked. eg. this worked <artifactId>database-ervice</artifactId> this did not database-service
Edit:
When using Postman to do the put request I got
Package "io.XXX.mydomain.xyz-service" is already associated with another repository. so realised that the package was previously deplloyed in another repo.
The maven-deployer-plugin is extremely poor at reporting the error message of the PUT response so had to use mintm to lookup the url and Postman to figure out the message.
I'm using Android Studio and desperately trying to get gradle to publish both my debug & release aar's to artifactory with separate repoKeys. Preferably as two separate tasks. I have read this excellent guide, but I don't want to change my gradle file each time in order to deploy.
I can easily create two pom files, but have not managed to make the artifactory plugin dynamic enough to switch my two rep keys.
I feel this is the closest I've come but it's not quite there:
String art_repo = ''
artifactory {
contextUrl = 'https://www.myjfrogrepo.com'
publish {
repository {
// The Artifactory repository key to publish to
repoKey = "${art_repo}"
I have then created a custom task which sets the art_repo variable.
task debugPublishTojFrog {
group "Publishing"
art_repo = 'libs-snapshot-local'
art_publicationName = 'debugAar'
doLast {
println "Successfully published ${art_repo} to jFrog"
}
}
debugPublishTojFrog.finalizedBy artifactoryPublish
This responds with the error
Target repository cannot be empty
This leads me to think the repoKey is set at build time and not at run time because my custom task's changes seem to be ignored.
Any suggestions really would be very much appreciated.
A standard way to do this in gradle is to test for the version you are about to publish.
This is exactly what the guide you link to advocates:
repoKey = libraryVersion.endsWith('SNAPSHOT') ? 'libs-snapshot-local' : 'libs-release-local'
What is wrong with this solution?
Edit: If the problem lies with having to change gradle or the gradle.properties file, why not use properties from the command line.
repoKey = project.hasProperty('releaseVersion') ? 'libs-release-local' : 'libs-snapshot-local'
And build your snapshot with
gradle build
And build your release with
gradle build -PreleaseVersion=1.0.0-GA
You can also use this releaseVersion property at several other locations, like your software metadata, your publication information...
Currently I have a react native app and the issue that I have is that is very time consuming to update the version on every build or commit.
Also, I have Sentry enabled so every time I build, some builds get the same version so some crashes are hard to determine where they came from.
Lastly, updating the version manually is error prone.
How can I setup my builds to generate an automatic version every time I build and forget about all of this manual task?
While the currently accepted answer will work, there is a much simpler, and therefore more reliable way to do it.
You can actually read the value set in package.json right from build.gradle.
Modify your android/app/build.gradle:
// On top of your file import a JSON parser
import groovy.json.JsonSlurper
// Create an easy to use function
def getVersionFromNpm() {
// Read and parse package.json file from project root
def inputFile = new File("$rootDir/../package.json")
def packageJson = new JsonSlurper().parseText(inputFile.text)
// Return the version, you can get any value this way
return packageJson["version"]
}
android {
defaultConfig {
applicationId "your.app.id"
versionName getVersionFromNpm()
}
}
This way you won't need a pre-build script or anything, it will just work.
Since I was working with this for several days, I decided to share with everyone how I did it, because it could help others.
Tools used:
GitVersion: We will use GitVersion to generate a semantic version automatically depending on many factors like current branch, tags, commits, etc. The toold does an excellent job and you can forget about naming your versions. Of course, if you set a tag to a commit, it will use that tag as name.
PowerShell: This command line OS built by Microsoft has the ability to be run from Mac, Linux or Windows, and I chose it because the builds can be agnostic of the OS version. For example I develop on Windows but the build machine has MacOS.
Edit App build.gradle
The app gradle only needs one line added at the end of it. In my case I have the Google Play Services gradle and I added it after that.
apply from: 'version.gradle'
version.gradle
This file should be in the same folder as your app gradle and this is the content:
task updatePackage(type: Exec, description: 'Updating package.json') {
commandLine 'powershell', ' -command ' , '$semver=(gitversion /showvariable Semver); Set-Content -path version.properties -value semver=$semver; npm version --no-git-tag-version --allow-same-version $semver'
}
preBuild.dependsOn updatePackage
task setVariantVersion {
doLast {
if (plugins.hasPlugin('android') || plugins.hasPlugin('android-library')) {
def autoIncrementVariant = { variant ->
variant.mergedFlavor.versionName = calculateVersionName()
}
if (plugins.hasPlugin('android')){
//Fails without putting android. first
android.applicationVariants.all { variant -> autoIncrementVariant(variant) }
}
if (plugins.hasPlugin('android-library')) {
//Probably needs android-library before libraryVariants. Needs testing
libraryVariants.all { variant -> autoIncrementVariant(variant) }
}
}
}
}
preBuild.dependsOn setVariantVersion
setVariantVersion.mustRunAfter updatePackage
ext {
versionFile = new File('version.properties')
calculateVersionName = {
def version = readVersion()
def semver = "Unknown"
if (version != null){
semver = version.getProperty('semver')
}
return semver
}
}
Properties readVersion() {
//It gets called once for every variant but all get the same version
def version = new Properties()
try {
file(versionFile).withInputStream { version.load(it) }
} catch (Exception error) {
version = null
}
return version
}
Now, let's review what the script is actually doing:
updatePackage: This task runs at the very beginning of your build (actually before preBuild) and it executes gitversion to get the current version and then creates a version.properties file which later be read by gradle to take the version.
setVariantVersion: This is called afterEvaluate on every variant. Meaning that if you have multiple builds like debug, release, qa, staging, etc, all will get the same version. For my use case this is fine, but you might want to tweak this.
Task Order: One thing that bothered me was that the version was being run before the file was generated. This is fixed by using the mustRunAfter tag.
PowerShell Script Explained
This is the script that gets run first. Let's review what is doing:
$semver=(gitversion /showvariable Semver);
Set-Content -path props.properties -value semver=$semver;
npm version --no-git-tag-version --allow-same-version $semver
Line 1: gitversion has multiple type of versions. If you run it without any parameter you will get a json file with many variants. Here we are saying that we only want the SemVer. (See also FullSemVer)
Line 2: PowerShell way to create a file and save the contents to it. This can be also made with > but I had encoding issues and the properties file was not being read.
Line 3: This line updates your package.json version. By default it saves a commit to git with the new version. --no-git-tag-version makes sure you don't override it.
And that is it. Now every time you make a build, the version should be generated automatically, your package.json updated and your build should have that specific version name.
App Center
Since I am using App Center to make the builds, I will tell you how you can use this in a Build machine. You only need to use a custom script.
app-center-pre-build.sh
#!/usr/bin/env sh
#Installing GitVersion
OS=$(uname -s)
if [[ $OS == *"W64"* ]]; then
echo "Installing GitVersion with Choco"
choco install GitVersion.Portable -y
else
echo "Installing GitVersion with Homebrew"
brew install --ignore-dependencies gitversion
fi
This is needed because GitVersion is not currently a part of the build machines. Also, you need to ignore the mono dependency when installing, otherwise you get an error when brew tries to link the files.
The #MacRusher version was fine for me. Just for further readers, I had to add .toInteger() to make it work. Since I'm using yarn version --patch to automatically upgrade the version in package.json I also had to take only the two first characters.
Here is the new version:
// On top of your file import a JSON parser
import groovy.json.JsonSlurper
def getVersionFromPackageJson() {
// Read and parse package.json file from project root
def inputFile = new File("$rootDir/../package.json")
def packageJson = new JsonSlurper().parseText(inputFile.text)
// Return the version, you can get any value this way
return packageJson["version"].substring(0,2).toInteger()
}
android {
defaultConfig {
applicationId "your.app.id"
versionName getVersionFromPackageJson()
}
}
I've recently uploaded my github project to bintray and successfully synced it with JCenter repository.
I used this tutorial:
http://inthecheesefactory.com/blog/how-to-upload-library-to-jcenter-maven-central-as-dependency/en
So my gradle dependency was :
dependencies {
compile 'com.github.danylo2006:hashtag-helper:1.1.0'
}
In order to upload it I've modified my build.gradle and added relevant peace of script. Everything like in the tutorial.
... some code here
ext {
bintrayRepo = 'maven'
bintrayName = 'hashtag-helper'
publishedGroupId = 'com.github.danylo2006'
libraryName = 'HashTagHelper'
artifact = 'hashtag-helper'
libraryDescription = 'This is a library designed for highlighting hashtags ("#example") and catching click on them.'
siteUrl = 'https://github.com/danylo2006/HashTagHelper'
gitUrl = 'https://github.com/danylo2006/HashTagHelper.git'
libraryVersion = '1.1.0'
developerId = 'danylovolokh'
developerName = 'Danylo Volokh'
developerEmail = 'v.danylo#gmail.com'
licenseName = 'The Apache Software License, Version 2.0'
licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
allLicenses = ["Apache-2.0"]
}
Here is the tricky part:
I've changed my github nickname danylo2006 to danylovolokh and now I want to change gradle dependency:
dependencies {
compile 'com.github.danylo2006:hashtag-helper:1.1.0'
}
Change to:
dependencies {
compile 'com.github.danylovolokh:hashtag-helper:1.1.0'
}
I got groupId that I need from Sonatype
So I've modified my gradle script.
The only relevant change is :
publishedGroupId = 'com.github.danylo2006'
Has been changed to
publishedGroupId = 'com.github.danylovolokh'
I run the relative commands:
gradlew install
gradlew bintrayUpload
And I got BUILD_SUCCESSFULL
But if I add new dependency to any other gradle project I get an error that "Error:(36, 13) Failed to resolve: com.github.danylovolokh:hashtag-helper:1.1.0"
Inclusion to JCenter is done by the path of your groupId. JFrog needs to include the new path from your package to JCenter as well.
Please contact JFrog support at support#bintray.com
#JBaruch is correct. It seems that emailing bintray is the correct way to really get these things changed. But for completeness, I am attaching the response I received from Bintray. Hopefully posting their response will prevent them from getting bombarded by emails...
For context, I have a java repository with the package (groupID:artifact):
io.jeti.utils:serialize
There are currently versions (1.0.0/1.0.1/1.0.2/1.0.3/1.0.4/) using this groupID. I asked them to change this to
io.jeti:serialize
And in fact, I already pushed versions (1.0.5/1.0.6) to bintray with this shortened groupID. This was the response:
We understand your use case. In such cases, we recommend creating a
new package and submit a new inclusion request. Please let me explain,
let's take 'serialize' package from your java repo for example.
Currently it has 2 path prefixes when only one is synced with Jcenter:
io/jeti/utils/serialize/ -> Synced io/jeti/serialize -> doesn't exist
in jcenter
Relinking the new groupId, will cause the old/current groupId
(io/jeti/utils) and its versions (1.0.0/1.0.1/1.0.2/1.0.3/1.0.4/) to
be un-resolvable when since it rely on the old groupId. This might
broke current integrations with your builds and scripts. Therefore,
the best approach is to create a new package (e.g serialize2), submit
a new inclusion request (which includes the new groupId -
io/jeti/serialize) and we will approve it and make it synced with
JCenter. In this case, you will get a full resolution of all of your
existing versions of the package (as well as 1.0.5/1.0.6).
Please let us know how to proceed.
My painfully acquired advice would be to create a new bintray package and ask for that to be published to the new groupId. I have tried to move an existing package and 48 hours and 20 messages to and from JFrog support have left me unable to publish my original package at the old or new location, nor a new package at the new location.
In the end I have had to register a new domain name to host my project, as bintray have effectively denied access to the groupId I was trying to change to.