From 518f6460419d8b1cf28a8a5d81b1a3bcd8e140d2 Mon Sep 17 00:00:00 2001 From: Aleksandr Mirko Date: Sun, 15 Sep 2024 10:59:24 +0100 Subject: [PATCH 1/9] Remove Sonatype supoporting --- CHANGELOG.md | 15 +- README.md | 91 +++--------- RELEASING.md | 19 +-- docs/releasing/01-setup.md | 13 -- docs/releasing/02-prepare-release-commit.md | 9 +- ...y.md => 03-publish-to-local-repository.md} | 6 +- .../04-publish-a-snapshot-to-sonatype.md | 15 -- .../05-publish-a-release-build-to-sonatype.md | 32 ---- .../06-publish-a-release-build-to-bintray.md | 15 -- ...a-release-build-to-gradle-plugin-portal.md | 4 +- .../08-prepare-alpha-version-commit.md | 12 ++ ...08-prepare-next-snapshot-version-commit.md | 16 -- gradle/libs.versions.toml | 4 +- plugin/build.gradle.kts | 3 - plugin/config/maven-publish.gradle | 140 ------------------ plugin/config/publish-methods.gradle | 8 - plugin/gradle.properties | 3 +- sample-aar/build.gradle | 8 +- sample-groovy/build.gradle | 7 +- settings.gradle.kts | 4 +- 20 files changed, 70 insertions(+), 354 deletions(-) rename docs/releasing/{03-publish-a-snapshot-to-local-repository.md => 03-publish-to-local-repository.md} (70%) delete mode 100644 docs/releasing/04-publish-a-snapshot-to-sonatype.md delete mode 100644 docs/releasing/05-publish-a-release-build-to-sonatype.md delete mode 100644 docs/releasing/06-publish-a-release-build-to-bintray.md create mode 100644 docs/releasing/08-prepare-alpha-version-commit.md delete mode 100644 docs/releasing/08-prepare-next-snapshot-version-commit.md delete mode 100644 plugin/config/maven-publish.gradle diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f36f11..9080340 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +# 1.4.3 + +##### Breaking Changes +* Remove support of Sonatype. It means that you can't use the plugin from Maven Central. You must to use the Gradle Portal. + To do this, you need to add the following code to your `settings.gradle.kts`: + ```kotlin + pluginManagement { + repositories { + gradlePluginPortal() + } + } + ``` + # 1.4.2 ##### Add @@ -6,7 +19,7 @@ ##### Fix * Fix correct mustRunAfter publish task for `assemble*` and `bundle*` tasks for Gradle 8. -##### Breaking changes +##### Breaking Changes Changed `releaseNotes` configuration block. Instead of ``` diff --git a/README.md b/README.md index 764ff7f..3804643 100644 --- a/README.md +++ b/README.md @@ -8,13 +8,12 @@ Huawei AppGallery Publishing Gradle Plugin -[![Maven Central](https://img.shields.io/maven-central/v/ru.cian/huawei-publish-gradle-plugin.svg)](https://search.maven.org/search?q=a:huawei-publish-gradle-plugin) - + [![License](https://img.shields.io/github/license/srs/gradle-node-plugin.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) -The plugin allows to publish the android release build files (`*.apk` and `*.aab`) to the Huawei AppGallery by use official [Huawei Publish API (v2)](https://developer.huawei.com/consumer/en/doc/development/AppGallery-connect-References/agcapi-appid-list_v2) +The plugin allows to publish the android release build files (`*.apk` and `*.aab`) to the Huawei AppGallery by use official [Huawei Publish API (v2)](https://developer.huawei.com/consumer/en/doc/AppGallery-connect-References/agcapi-obtain_token-0000001158365043) -:construction: _That's unofficial plugin. We did it for himself and share it for you._ +:construction: _That's unofficial plugin. We made it for ourselves and are sharing it for you._ # Table of contents @@ -79,78 +78,22 @@ plugins { } ``` -
-Snapshot builds are also available -___ - -You'll need to add the Sonatype snapshots repository. -Look for the actual version of the snapshot in the name of the opened `snapshot-` repository branch. - -in `./settings.gradle` - -```kotlin -pluginManagement { - - resolutionStrategy { - eachPlugin { - if(requested.id.namespace == "ru.cian") { - useModule("ru.cian:huawei-publish-gradle-plugin:") - } - } - } - - plugins { - id("ru.cian.huawei-publish-gradle-plugin") version huaweiPublish apply false - } - - repositories { - maven { url 'https://oss.sonatype.org/content/repositories/snapshots' } - } -} -``` -___ -
- ## Using the `apply` method ```groovy buildscript { repositories { - mavenCentral() // or gradlePluginPortal() - } - - dependencies { - classpath "ru.cian:huawei-publish-gradle-plugin:" - } -} - -apply plugin: 'com.android.application' -apply plugin: 'ru.cian.huawei-publish-gradle-plugin' -``` -
-Snapshot builds are also available -___ - -You'll need to add the Sonatype snapshots repository. -Look for the actual version of the snapshot in the name of the opened `snapshot-` repository branch. - -```kotlin -buildscript { - repositories { - maven { url 'https://oss.sonatype.org/content/repositories/snapshots' } + gradlePluginPortal() } dependencies { - classpath "ru.cian:huawei-publish-gradle-plugin:-SNAPSHOT" + classpath "ru.cian:huawei-publish-gradle-plugin:" } } apply plugin: 'com.android.application' apply plugin: 'ru.cian.huawei-publish-gradle-plugin' ``` -___ - -
## Quickstart Plugin Configuration @@ -216,8 +159,9 @@ huaweiPublish { instances { create("release") { /** - * Path to json file with AppGallery credentials params (`client_id` and `client_secret`). + * Description: Path to json file with AppGallery credentials params (`client_id` and `client_secret`). * How to get credentials see [AppGallery Connect API Getting Started](https://developer.huawei.com/consumer/en/doc/development/AppGallery-connect-Guides/agcapi-getstarted). + * * Plugin credential json example: * { * "client_id": "", @@ -232,20 +176,29 @@ huaweiPublish { /** * Deploy type. Available values: - * '`publish`' to deploy and submit build on users; - * '`draft`' to deploy and save as draft without submit on users; - * '`upload-only`' to deploy without draft saving and submit on users; * Type String (Optional) * Default value: `publish` - * CLI `--deployType` + * Gradle: available values: + * ru.cian.huawei.publish.DeployType.PUBLISH + * ru.cian.huawei.publish.DeployType.UPLOAD_ONLY + * ru.cian.huawei.publish.DeployType.DRAFT + * CLI: `--deployType`, available values: + * 'publish' to deploy and submit build on users; + * 'draft' to deploy and save as draft without submit on users; + * 'upload-only' to deploy without draft saving and submit on users; */ deployType = ru.cian.huawei.publish.DeployType.PUBLISH /** - * 'apk' or 'aab' for corresponding build format. + * Description: Build file format. * Type: String (Optional) * Default value: `apk` - * CLI: `--buildFormat` + * Gradle: available values: + * ru.cian.huawei.publish.BuildFormat.APK + * ru.cian.huawei.publish.BuildFormat.AAB + * CLI: `--buildFormat`, available values: + * 'apk' – for APK build format; + * 'aab' – for AAB build format. */ buildFormat = ru.cian.huawei.publish.BuildFormat.APK diff --git a/RELEASING.md b/RELEASING.md index 3acbb19..f0f775f 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -6,23 +6,18 @@ elaborate and requires a good deal of local configuration. This guide should wa you through it. It won't do anyone outside of KeepSafe any good, but the workflow is representative of just about any project deploying via Sonatype. -We currently deploy to both Maven Central (via Sonatype's OSS Nexus instance) and to -plugins.gradle.org. +We currently deploy to plugins.gradle.org. ## Prerequisites 1. A *published* GPG code-signing key -2. A Sonatype Nexus OSS account with permission to publish in ru.cian -3. A plugins.gradle.org account with permission to publish in ru.cian -4. Permission to push directly to https://github.com/cianru/huawei-publish-gradle-plugin +1. A plugins.gradle.org account with permission to publish in ru.cian +1. Permission to push directly to https://github.com/cianru/huawei-publish-gradle-plugin ## Contents page 1. [Setup](docs/releasing/01-setup.md) -2. [Prepare Release Commit](docs/releasing/02-prepare-release-commit.md) -3. [Pushing a SNAPSHOT build to local repository](docs/releasing/03-publish-a-snapshot-to-local-repository.md) -4. [Pushing a SNAPSHOT build to Sonatype](docs/releasing/04-publish-a-snapshot-to-sonatype.md) -5. [Pushing a release build to Sonatype](docs/releasing/05-publish-a-release-build-to-sonatype.md) -6. [Pushing a release build to Bintray (DEPRECATED)](docs/releasing/06-publish-a-release-build-to-bintray.md) -7. [Pushing a release build to Gradle Plugin Portal](docs/releasing/07-publish-a-release-build-to-gradle-plugin-portal.md) -8. [Prepare Next Snapshot Version Commit](docs/releasing/08-prepare-next-snapshot-version-commit.md) +1. [Prepare Release Commit](docs/releasing/02-prepare-release-commit.md) +1. [Pushing a build to local repository](docs/releasing/03-publish-to-local-repository) +1. [Pushing a release build to Gradle Plugin Portal](docs/releasing/07-publish-a-release-build-to-gradle-plugin-portal.md) +1. [Prepare Next Alpha Version Commit](docs/releasing/08-prepare-alpha-version-commit) diff --git a/docs/releasing/01-setup.md b/docs/releasing/01-setup.md index bf284f8..64e0ff8 100644 --- a/docs/releasing/01-setup.md +++ b/docs/releasing/01-setup.md @@ -1,18 +1,5 @@ ## Setup -1. Add your GPG key to your github profile - this is required - for github to know that your commits and tags are "verified". -1. Configure your code-signing key in ~/.gradle.properties: - ```gradle - signing.keyId= - signing.password= - signing.secretKeyRingFile=/path/to/your/secring.gpg - ``` -1. Configure your Sonatype credentials in ~/.gradle/gradle.properties: - ```gradle - SONATYPE_NEXUS_USERNAME= - SONATYPE_NEXUS_PASSWORD= - ``` 1. Configure git with your codesigning key; make sure it's the same as the one you use to sign binaries (i.e. it's the same one you adaded to gradle.properties): ```bash diff --git a/docs/releasing/02-prepare-release-commit.md b/docs/releasing/02-prepare-release-commit.md index 3abe41e..5810803 100644 --- a/docs/releasing/02-prepare-release-commit.md +++ b/docs/releasing/02-prepare-release-commit.md @@ -1,14 +1,15 @@ ## Prepare Release Commit -1. Edit ./plugin/gradle.properties, remove '-SNAPSHOT' from the VERSION property -2. Make a *signed* commit: +1. Edit the `gradle.properties` file: + Remove `-alpha` from the `VERSION_NAME` and set the version to the release version. For example: `1.0.0`. +1. Make a *signed* commit: ```bash git commit -m "Release vX.Y.Z" ``` -3. Make a *signed* tag (check existing tags for message format): +1. Make a *signed* tag (check existing tags for message format): ```bash git tag -a "vX.Y.Z" -m "vX.Y.Z" ``` -4. Push all of our work to Github to make it official: +1. Push all of our work to Github to make it official: ```bash git push --tags origin master diff --git a/docs/releasing/03-publish-a-snapshot-to-local-repository.md b/docs/releasing/03-publish-to-local-repository.md similarity index 70% rename from docs/releasing/03-publish-a-snapshot-to-local-repository.md rename to docs/releasing/03-publish-to-local-repository.md index 34a62ad..c80ee8e 100644 --- a/docs/releasing/03-publish-a-snapshot-to-local-repository.md +++ b/docs/releasing/03-publish-to-local-repository.md @@ -1,13 +1,9 @@ -## Pushing a SNAPSHOT build to local repository +## Pushing a build to local repository 1. Open the plugin directory: ``` cd ./plugin ``` -2. Edit the `gradle.properties` file: - ```bash - IS_SNAPSHOT=true - ``` 3. Publish to local repository ```bash ./gradlew :plugin:publishToMavenLocal diff --git a/docs/releasing/04-publish-a-snapshot-to-sonatype.md b/docs/releasing/04-publish-a-snapshot-to-sonatype.md deleted file mode 100644 index 24aba6f..0000000 --- a/docs/releasing/04-publish-a-snapshot-to-sonatype.md +++ /dev/null @@ -1,15 +0,0 @@ -## Pushing a SNAPSHOT build to Sonatype - -1. Open the plugin directory: - ``` - cd ./plugin - ``` -2. Edit the `gradle.properties` file: - ```bash - IS_SNAPSHOT=true - ``` -3. Upload binaries to Sonatype: - ```bash - ./gradlew :plugin:publishHuaweiPublicationToMavenRepository - ``` -4. Check snapshot: [nexus-search](https://oss.sonatype.org/#nexus-search;quick~ru.cian) diff --git a/docs/releasing/05-publish-a-release-build-to-sonatype.md b/docs/releasing/05-publish-a-release-build-to-sonatype.md deleted file mode 100644 index ab112d4..0000000 --- a/docs/releasing/05-publish-a-release-build-to-sonatype.md +++ /dev/null @@ -1,32 +0,0 @@ -## Pushing a release build to Sonatype - -1. Open the plugin directory: - ``` - cd ./plugin - ``` -1. Edit the `gradle.properties` file: - ```bash - IS_SNAPSHOT=false - ``` -1. Edit `README.md` so that Gradle examples point to the new version -1. Edit changelog, add relevant changes, note the date and new version (follow the existing pattern) -1. Verify that the everything works: - ```bash - ./gradlew clean check - ``` -1. Verify that the code style is correct: - ```bash - ./gradlew detekt - ``` -1. Upload binaries to Sonatype: - ```bash - ./gradlew :plugin:publishHuaweiPublicationToMavenRepository - ``` -1. Check uploaded files and version Sonatype site: [search.maven.org](https://search.maven.org/search?q=ru.cian) - and [repo1.maven.org](https://repo1.maven.org/maven2/ru/cian/huawei-publish-gradle-plugin/) -1. Go to [oss.sonatype.org](https://oss.sonatype.org), log in with your credentials -1. Click "Staging Repositories" -1. Find the "ru.cian" repo, usually at the bottom of the list -1. "Close" the repository (select it then click the "close" button up top), the text field doesn't matter so put whatever you want in it -1. Wait until that's done -1. "Release" the repository, leave the checkbox "Automatically Drop" checked. Yeap, we're in Maven Central now! diff --git a/docs/releasing/06-publish-a-release-build-to-bintray.md b/docs/releasing/06-publish-a-release-build-to-bintray.md deleted file mode 100644 index 419ac3d..0000000 --- a/docs/releasing/06-publish-a-release-build-to-bintray.md +++ /dev/null @@ -1,15 +0,0 @@ -## Pushing a release build to Bintray - -1. Open the plugin directory: - ``` - cd ./plugin - ``` -1. Edit the `gradle.properties` file: - ```bash - IS_SNAPSHOT=false - ``` -1. Upload binaries to Bintray: - ```bash - ./gradlew build :plugin:bintrayUpload - ``` -1. Check uploaded files and version Bintray site: [bintray.com](https://bintray.com/myumatov/ru.cian/huawei-publish-gradle-plugin) diff --git a/docs/releasing/07-publish-a-release-build-to-gradle-plugin-portal.md b/docs/releasing/07-publish-a-release-build-to-gradle-plugin-portal.md index f81d49c..38788a4 100644 --- a/docs/releasing/07-publish-a-release-build-to-gradle-plugin-portal.md +++ b/docs/releasing/07-publish-a-release-build-to-gradle-plugin-portal.md @@ -5,9 +5,7 @@ cd ./plugin ``` 1. Edit the `gradle.properties` file: - ```bash - IS_SNAPSHOT=false - ``` + Remove `-alpha` from the `VERSION_NAME` and set the version to the release version. For example: `1.0.0`. 1. Upload binaries to Gradle's plugin portal: ```bash ./gradlew :plugin:publishPlugins diff --git a/docs/releasing/08-prepare-alpha-version-commit.md b/docs/releasing/08-prepare-alpha-version-commit.md new file mode 100644 index 0000000..c225ad1 --- /dev/null +++ b/docs/releasing/08-prepare-alpha-version-commit.md @@ -0,0 +1,12 @@ +## Prepare Next Alpha Version Commit + +1. Create new `snapshot-` Git branch +1. Open the plugin directory: + ``` + cd ./plugin + ``` +1. Edit the `gradle.properties` file to set new `VERSION_NAME`+ `-alpha` version. For example: `1.0.0-alpha01`. +1. Make a *signed* commit: + ```bash + git commit -m "Prepare next development version" + ``` diff --git a/docs/releasing/08-prepare-next-snapshot-version-commit.md b/docs/releasing/08-prepare-next-snapshot-version-commit.md deleted file mode 100644 index 46f026d..0000000 --- a/docs/releasing/08-prepare-next-snapshot-version-commit.md +++ /dev/null @@ -1,16 +0,0 @@ -## Prepare Next Snapshot Version Commit - -1. Create new `snapshot-` Git branch -2. Open the plugin directory: - ``` - cd ./plugin - ``` -3. Edit the `gradle.properties` file to set new `VERSION_NAME` version. -4. Edit the `gradle.properties` file: -```bash -IS_SNAPSHOT=true -``` -5. Make a *signed* commit: - ```bash - git commit -m "Prepare next development version" - ``` diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 223df18..3a8aa09 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,7 @@ kotlin = "1.9.22" detekt = "1.23.4" junitJupiter = "5.9.3" androidGradlePlugin = "8.2.0" -sampleHuaweiPlugin = "1.4.3-SNAPSHOT" +sampleHuaweiPlugin = "1.4.3-alpha01" [libraries] appcompat = "androidx.appcompat:appcompat:1.6.1" @@ -39,5 +39,5 @@ dcendents = { id = "com.github.dcendents", version = "plugin:2.1" } bintray = { id = "com.jfrog.bintray", version = "1.8.5" } pluginPublish = { id = "com.gradle.plugin-publish", version = "0.15.0" } kotlinJvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } -benManesVersions = { id = "com.github.ben-manes.versions", version = "0.46.0" } +benManesVersions = { id = "com.github.ben-manes.versions", version = "0.47.0" } detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" } diff --git a/plugin/build.gradle.kts b/plugin/build.gradle.kts index 850e572..aeab6b5 100644 --- a/plugin/build.gradle.kts +++ b/plugin/build.gradle.kts @@ -4,14 +4,11 @@ plugins { `signing` alias(libs.plugins.detekt) alias(libs.plugins.pluginPublish) - alias(libs.plugins.bintray) alias(libs.plugins.dokka) alias(libs.plugins.kotlinJvm) } apply(from = "$projectDir/config/check-jdk.gradle") -apply(from = "$projectDir/config/maven-publish.gradle") -apply(from = "$projectDir/config/bintray-publish.gradle") apply(from = "$projectDir/config/gradle-portal.gradle") detekt { diff --git a/plugin/config/maven-publish.gradle b/plugin/config/maven-publish.gradle deleted file mode 100644 index f72d76c..0000000 --- a/plugin/config/maven-publish.gradle +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright 2020 Aleksandr Mirko - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -apply from: "$projectDir/config/publish-methods.gradle" - -private String getRepositoryUsername() { - return hasProperty('SONATYPE_NEXUS_USERNAME') - ? SONATYPE_NEXUS_USERNAME - : System.env.SONATYPE_NEXUS_USERNAME -} - -private String getRepositoryPassword() { - return hasProperty('SONATYPE_NEXUS_PASSWORD') - ? SONATYPE_NEXUS_PASSWORD - : System.env.SONATYPE_NEXUS_PASSWORD -} - -private String getRepositoryUrl() { - return isReleaseBuild() - ? "https://oss.sonatype.org/service/local/staging/deploy/maven2/" - : "https://oss.sonatype.org/content/repositories/snapshots/" -} - -def hasDeploymentTask(Project project) { - def deploymentTasks = [ - "publishPlugins", - "publish" - ] - deploymentTasks.any { project.gradle.taskGraph.hasTask(it) } -} - -task sourceJar(type: Jar) { - archiveClassifier.set("sources") - from sourceSets.main.allSource -} - -task javadocJar(type: Jar, dependsOn: dokkaHtml) { - archiveClassifier.set("javadoc") - from dokkaHtml.outputDirectory -} - -jar { - manifest { - attributes( - "Implementation-Title": POM_ARTIFACT_ID, - "Implementation-Version": getVersionName() - ) - } -} - -artifacts { - archives jar - archives sourceJar - archives javadocJar -} - -publishing { - publications { - huawei(MavenPublication) { - groupId = GROUP - artifactId = POM_ARTIFACT_ID - version = getVersionName() - - from components.java - artifact sourceJar - artifact javadocJar - - pom { - name = POM_NAME - packaging = POM_PACKAGING - description = POM_DESCRIPTION - url = POM_URL - - scm { - url = POM_SCM_URL - connection = POM_SCM_CONNECTION - developerConnection = POM_SCM_DEV_CONNECTION - } - - licenses { - license { - name = POM_LICENSE_NAME - url = POM_LICENSE_URL - distribution = POM_LICENSE_DIST - } - } - - developers { - developer { - id = POM_DEVELOPER_ID - name = POM_DEVELOPER_NAME - email = POM_DEVELOPER_EMAIL - } - } - - organization { - name = POM_DEVELOPER_NAME - url = POM_DEVELOPER_CITE - } - } - } - } - - repositories { - maven { - url = getRepositoryUrl() - credentials { - username = getRepositoryUsername() - password = getRepositoryPassword() - } - } - } -} - -signing { - required { isReleaseBuild() && hasDeploymentTask(project) } - sign project.publishing.publications -} - -// At the moment, signing kotlin metadata fails with a Gradle error for snapshots. -// To work around, we'll need to suppress signing for them, which is different from -// 'signing.required = false'. -if (!isReleaseBuild()) { - tasks.withType(Sign) { - onlyIf { isReleaseBuild() && hasDeploymentTask(project) } - } -} diff --git a/plugin/config/publish-methods.gradle b/plugin/config/publish-methods.gradle index 51231c1..c9a07c1 100644 --- a/plugin/config/publish-methods.gradle +++ b/plugin/config/publish-methods.gradle @@ -1,15 +1,7 @@ ext { - isReleaseBuild = this.&isReleaseBuild getVersionName = this.&getVersionName } -private boolean isReleaseBuild() { - return IS_SNAPSHOT != "true" -} - private String getVersionName() { - if (!isReleaseBuild()) { - return VERSION_NAME + "-SNAPSHOT" - } return VERSION_NAME } diff --git a/plugin/gradle.properties b/plugin/gradle.properties index 082b9ad..a8e2322 100644 --- a/plugin/gradle.properties +++ b/plugin/gradle.properties @@ -9,8 +9,7 @@ android.enableJetifier=true #################################################################################################### GROUP=ru.cian -VERSION_NAME=1.4.3 -IS_SNAPSHOT=true +VERSION_NAME=1.4.3-alpha01 REQUIRED_JDK_VERSION=17 diff --git a/sample-aar/build.gradle b/sample-aar/build.gradle index a2f7bbb..5819c23 100644 --- a/sample-aar/build.gradle +++ b/sample-aar/build.gradle @@ -5,8 +5,8 @@ apply plugin: 'ru.cian.huawei-publish' buildscript { repositories { + gradlePluginPortal() mavenCentral() - maven { url 'https://oss.sonatype.org/content/repositories/snapshots' } } dependencies { @@ -48,9 +48,3 @@ android { abortOnError false } } - -beforeEvaluate { - println("-------------------------------------------------------------------------") - println("Should get error!") - println("-------------------------------------------------------------------------") -} diff --git a/sample-groovy/build.gradle b/sample-groovy/build.gradle index 949f324..0fbadf9 100644 --- a/sample-groovy/build.gradle +++ b/sample-groovy/build.gradle @@ -1,18 +1,17 @@ buildscript { repositories { mavenLocal() - maven { url 'https://oss.sonatype.org/content/repositories/snapshots' } - mavenCentral() + gradlePluginPortal() } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:" + libs.versions.kotlin.get() - classpath "ru.cian:huawei-publish-gradle-plugin:" + libs.versions.sampleHuaweiPlugin.get() + classpath "ru.cian:plugin:" + libs.versions.sampleHuaweiPlugin.get() } } apply plugin: "com.android.application" -apply plugin: "ru.cian.huawei-publish" +apply plugin: "ru.cian.huawei-publish-gradle-plugin" huaweiPublish { instances { diff --git a/settings.gradle.kts b/settings.gradle.kts index 81f75bf..c692094 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -13,17 +13,15 @@ pluginManagement { resolutionStrategy { eachPlugin { if(requested.id.namespace == "ru.cian") { - useModule("ru.cian:huawei-publish-gradle-plugin:${huaweiPublish}") + useModule("ru.cian:plugin:${huaweiPublish}") } } } repositories { mavenLocal() - maven { url = uri("https://oss.sonatype.org/content/repositories/snapshots") } google() gradlePluginPortal() - mavenCentral() maven { url = uri("https://plugins.gradle.org/m2/") } } } From f46ac0678b19ac440f73cb83c355a3267c79bc40 Mon Sep 17 00:00:00 2001 From: Aleksandr Mirko Date: Fri, 27 Sep 2024 22:42:24 +0100 Subject: [PATCH 2/9] Use single samplePublishVersion --- README.md | 6 ++++-- plugin/config/detekt/detekt-config.yml | 2 ++ settings.gradle.kts | 8 ++++++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3804643..8d5302c 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ The plugin allows to publish the android release build files (`*.apk` and `*.aab - [Adding the plugin to your project](#adding-the-plugin-to-your-project) - [Using the Gradle plugin DSL](#using-the-gradle-plugin-dsl) - [Using the `apply` method](#using-the-apply-method) - - [Quickstart Plugin Configuration](#quickstart-plugin-configuration) + - [Quick Start Plugin Configuration](#quick-start-plugin-configuration) - [Full Plugin Configuration](#full-plugin-configuration) - [Plugin usage](#plugin-usage) - [CLI Plugin Configuration](#cli-plugin-configuration) @@ -95,7 +95,9 @@ apply plugin: 'com.android.application' apply plugin: 'ru.cian.huawei-publish-gradle-plugin' ``` -## Quickstart Plugin Configuration +## Quick Start Plugin Configuration + +Before using the plugin you should get `client_id` and `client_secret` from [AppGallery Connect API Getting Started](https://developer.huawei.com/consumer/en/doc/development/AppGallery-connect-Guides/agcapi-getstarted). Minimal configuration for plugin usage: diff --git a/plugin/config/detekt/detekt-config.yml b/plugin/config/detekt/detekt-config.yml index bbdb0e2..5b3999f 100644 --- a/plugin/config/detekt/detekt-config.yml +++ b/plugin/config/detekt/detekt-config.yml @@ -110,6 +110,8 @@ formatting: active: false PackageName: active: true + StringTemplate: + active: false SpacingAroundAngleBrackets: active: true SpacingAroundDoubleColon: diff --git a/settings.gradle.kts b/settings.gradle.kts index c692094..637343d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -8,12 +8,16 @@ include( pluginManagement { - val huaweiPublish = "1.4.2" + val libsVersionFile = file("gradle/libs.versions.toml") + val properties = java.util.Properties().apply { + libsVersionFile.reader().use { load(it) } + } + val samplePublishVersion = properties.getProperty("sampleHuaweiPlugin").replace("\"", "") resolutionStrategy { eachPlugin { if(requested.id.namespace == "ru.cian") { - useModule("ru.cian:plugin:${huaweiPublish}") + useModule("ru.cian:plugin:${samplePublishVersion}") } } } From 187f5e2aad631e4001109e4bcd3cf8ab460a6762 Mon Sep 17 00:00:00 2001 From: Aleksandr Mirko Date: Sat, 28 Sep 2024 21:28:31 +0100 Subject: [PATCH 3/9] Add mock server for testing --- gradle/libs.versions.toml | 1 + plugin/build.gradle.kts | 1 + .../huawei/publish/HuaweiPublishPlugin.kt | 35 ++++ .../cian/huawei/publish/HuaweiPublishTask.kt | 93 +++++++---- .../publish/service/HuaweiServiceImpl.kt | 22 ++- .../publish/service/MockHuaweiService.kt | 133 --------------- .../publish/service/mock/MockServerWrapper.kt | 10 ++ .../service/mock/MockServerWrapperImpl.kt | 157 ++++++++++++++++++ .../service/mock/MockServerWrapperStub.kt | 18 ++ .../huawei/publish/utils/BuildFileProvider.kt | 30 +--- .../utils/BuildFileProviderDeprecated.kt | 35 ++++ .../publish/utils/BuildFileProviderNew.kt | 36 ++++ .../ru/cian/huawei/publish/utils/Logger.kt | 2 +- 13 files changed, 373 insertions(+), 200 deletions(-) delete mode 100644 plugin/src/main/kotlin/ru/cian/huawei/publish/service/MockHuaweiService.kt create mode 100644 plugin/src/main/kotlin/ru/cian/huawei/publish/service/mock/MockServerWrapper.kt create mode 100644 plugin/src/main/kotlin/ru/cian/huawei/publish/service/mock/MockServerWrapperImpl.kt create mode 100644 plugin/src/main/kotlin/ru/cian/huawei/publish/service/mock/MockServerWrapperStub.kt create mode 100644 plugin/src/main/kotlin/ru/cian/huawei/publish/utils/BuildFileProviderDeprecated.kt create mode 100644 plugin/src/main/kotlin/ru/cian/huawei/publish/utils/BuildFileProviderNew.kt diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3a8aa09..60f85cf 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -20,6 +20,7 @@ appcompat = "androidx.appcompat:appcompat:1.6.1" kotlinBom = { group = "org.jetbrains.kotlin", name = "kotlin-bom", version.ref = "kotlin" } gson = "com.google.code.gson:gson:2.8.6" okHttp = "com.squareup.okhttp3:okhttp:4.12.0" +mockServer = "com.squareup.okhttp3:mockwebserver:4.9.3" androidGradlePlugin = { group = "com.android.tools.build", name = "gradle", version.ref = "androidGradlePlugin" } detektFormating = { group = "io.gitlab.arturbosch.detekt", name = "detekt-formatting", version.ref = "detekt" } detektLibraries = { group = "io.gitlab.arturbosch.detekt", name = "detekt-rules-libraries", version.ref = "detekt" } diff --git a/plugin/build.gradle.kts b/plugin/build.gradle.kts index aeab6b5..ec99a3c 100644 --- a/plugin/build.gradle.kts +++ b/plugin/build.gradle.kts @@ -80,6 +80,7 @@ dependencies { implementation(platform(libs.kotlinBom)) implementation(libs.gson) implementation(libs.okHttp) + implementation(libs.mockServer) compileOnly(libs.androidGradlePlugin) detektPlugins(libs.detektFormating) diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishPlugin.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishPlugin.kt index 491173b..7800255 100644 --- a/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishPlugin.kt +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishPlugin.kt @@ -1,5 +1,6 @@ package ru.cian.huawei.publish +import com.android.build.api.artifact.SingleArtifact import com.android.build.api.variant.ApplicationAndroidComponentsExtension import com.android.build.api.variant.ApplicationVariant import com.android.build.api.variant.VariantSelector @@ -11,6 +12,8 @@ import org.gradle.kotlin.dsl.create import org.gradle.kotlin.dsl.getByType import org.gradle.kotlin.dsl.register import org.gradle.kotlin.dsl.withType +import java.io.File +import java.util.Optional class HuaweiPublishPlugin : Plugin { @@ -42,6 +45,23 @@ class HuaweiPublishPlugin : Plugin { val publishTaskName = "${HuaweiPublishTask.TASK_NAME}$variantName" val publishTask = project.tasks.register(publishTaskName, variant) scheduleTasksOrder(publishTask, project, variantName) +// +// +// val variantName = variant.name +// val variantApplicationId = variant.applicationId.get() +// val variantApkBuildFilePath = getFinalApkArtifactCompat(variant).singleOrNull()?.absolutePath +// val variantAabBuildFilePath = getFinalBundleArtifactCompat(variant).singleOrNull()?.absolutePath +//// val variantApkBuildFilePath = project.rootProject.path + "/app/build/outputs/bundle/release/app-release.aab" +//// val variantAabBuildFilePath = project.rootProject.path + "/app/build/outputs/apk/release/app-release.apk" +// val publishTaskName = "${HuaweiPublishTask.TASK_NAME}${variantName.capitalize()}" +// val publishTask = project.tasks.register( +// publishTaskName, +// variantApplicationId, +// variantName, +// Optional.ofNullable(variantApkBuildFilePath), +// Optional.ofNullable(variantAabBuildFilePath), +// ) +//// scheduleTasksOrder(publishTask, project, variantName) } private fun scheduleTasksOrder( @@ -65,4 +85,19 @@ class HuaweiPublishPlugin : Plugin { publishTask.get().mustRunAfter(assembleTask) } } + + // TODO(a.mirko): Remove after https://github.com/gradle/gradle/issues/16777 + // TODO(a.mirko): Remove after https://github.com/gradle/gradle/issues/16775 + private fun getFinalApkArtifactCompat(variant: ApplicationVariant): List { + val apkDirectory = variant.artifacts.get(SingleArtifact.APK).get() + return variant.artifacts.getBuiltArtifactsLoader().load(apkDirectory) + ?.elements?.map { element -> File(element.outputFile) } + ?: apkDirectory.asFileTree.matching { include("*.apk") }.map { it.absolutePath }.map { File(it) } + ?: emptyList() + } + + private fun getFinalBundleArtifactCompat(variant: ApplicationVariant): List { + val aabFile = variant.artifacts.get(SingleArtifact.BUNDLE).get().asFile + return listOf(aabFile) + } } diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishTask.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishTask.kt index 5abe842..2526a49 100644 --- a/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishTask.kt +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishTask.kt @@ -12,8 +12,10 @@ import ru.cian.huawei.publish.models.response.FileServerOriResultResponse import ru.cian.huawei.publish.models.response.SubmitResponse import ru.cian.huawei.publish.service.HuaweiService import ru.cian.huawei.publish.service.HuaweiServiceImpl -import ru.cian.huawei.publish.service.MockHuaweiService -import ru.cian.huawei.publish.utils.BuildFileProvider +import ru.cian.huawei.publish.service.mock.MockServerWrapper +import ru.cian.huawei.publish.service.mock.MockServerWrapperImpl +import ru.cian.huawei.publish.service.mock.MockServerWrapperStub +import ru.cian.huawei.publish.utils.BuildFileProviderDeprecated import ru.cian.huawei.publish.utils.ConfigProvider import ru.cian.huawei.publish.utils.Logger import ru.cian.huawei.publish.utils.RELEASE_DATE_TIME_FORMAT @@ -25,16 +27,32 @@ import ru.cian.huawei.publish.utils.FileWrapper @DisableCachingByDefault open class HuaweiPublishTask @Inject constructor( - private val variant: ApplicationVariant + private val variant: ApplicationVariant, +// private val variantApplicationId: String, +// private val variantName: String, +// private val variantApkBuildFilePath: Optional, +// private val variantAabBuildFilePath: Optional, ) : DefaultTask() { + private val logger by lazy { Logger(project) } + private lateinit var huaweiPublishExtension: HuaweiPublishExtension + + private val variantName = variant.name + + private val variantApplicationId = variant.applicationId.get() + init { group = PublishingPlugin.PUBLISH_TASK_GROUP description = "Upload and publish application build file " + - "to Huawei AppGallery Store for ${variant.name} buildType" + "to Huawei AppGallery Store for ${variantName} buildType" + + huaweiPublishExtension = project.extensions + .findByName(HuaweiPublishExtension.MAIN_EXTENSION_NAME) as? HuaweiPublishExtension + ?: throw IllegalArgumentException( + "Plugin extension '${HuaweiPublishExtension.MAIN_EXTENSION_NAME}' " + + "is not available at build.gradle of the application module" + ) } - - private val logger by lazy { Logger(project) } @get:Internal @set:Option( @@ -162,19 +180,10 @@ open class HuaweiPublishTask @TaskAction fun action() { - val huaweiService: HuaweiService = if (apiStub == true) MockHuaweiService() else HuaweiServiceImpl(logger) - val huaweiPublishExtension = project.extensions - .findByName(HuaweiPublishExtension.MAIN_EXTENSION_NAME) as? HuaweiPublishExtension - ?: throw IllegalArgumentException( - "Plugin extension '${HuaweiPublishExtension.MAIN_EXTENSION_NAME}' " + - "is not available at build.gradle of the application module" - ) - - val buildTypeName = variant.name - val extension = huaweiPublishExtension.instances.find { it.name.equals(buildTypeName, ignoreCase = true) } + val extension = huaweiPublishExtension.instances.find { it.name.equals(variantName, ignoreCase = true) } ?: throw IllegalArgumentException( "Plugin extension '${HuaweiPublishExtension.MAIN_EXTENSION_NAME}' " + - "instance with name '$buildTypeName' is not available" + "instance with name '$variantName' is not available" ) val cli = HuaweiPublishCliParam( @@ -199,8 +208,14 @@ open class HuaweiPublishTask logger.i("extension=$extension") logger.i("cli=$cli") - logger.v("Prepare input config") - val buildFileProvider = BuildFileProvider(variant = variant, logger = logger) + logger.v("1. Prepare input config") +// val buildFileProvider = BuildFileProviderNew( +// variantApkBuildFilePath = variantApkBuildFilePath.orElseGet(null), +// variantAabBuildFilePath = variantAabBuildFilePath.orElseGet(null), +// logger = logger, +// ) + val buildFileProvider = BuildFileProviderDeprecated(variant = variant, logger = logger) + val config = ConfigProvider( extension = extension, cli = cli, @@ -211,23 +226,30 @@ open class HuaweiPublishTask logger.v("Found build file: `${config.artifactFile.name}`") - logger.v("Get Access Token") + val mockServerWrapper = getMockServerWrapper(config=config) + mockServerWrapper.start() + + val huaweiService = HuaweiServiceImpl( + logger=logger, + baseEntryPoint=mockServerWrapper.getBaseUrl(), + ) + + logger.v("2. Get Access Token") val token = huaweiService.getToken( clientId = config.credentials.clientId, clientSecret = config.credentials.clientSecret ) logger.i("token=$token") - logger.v("Get App ID") - val applicationId = variant.applicationId.get() + logger.v("3. Get App ID") val appInfo = huaweiService.getAppID( clientId = config.credentials.clientId, accessToken = token, - packageName = applicationId + packageName = variantApplicationId ) logger.i("appInfo=$appInfo") - logger.v("Get Upload Url") + logger.v("4. Get Upload Url") val uploadUrl = huaweiService.getUploadingBuildUrl( clientId = config.credentials.clientId, accessToken = token, @@ -236,7 +258,7 @@ open class HuaweiPublishTask ) logger.i("uploadUrl=$uploadUrl") - logger.v("Upload build file '${config.artifactFile.path}'") + logger.v("5. Upload build file '${config.artifactFile.path}'") val fileInfoListResult = huaweiService.uploadBuildFile( uploadUrl = uploadUrl.uploadUrl, authCode = uploadUrl.authCode, @@ -248,7 +270,7 @@ open class HuaweiPublishTask config.releaseNotes?.descriptions?.forEachIndexed { index, releaseNote -> val newFeatures = releaseNote.newFeatures logger.v( - "Upload release notes: ${index + 1}/${config.releaseNotes.descriptions.size}, " + + "6. Upload release notes: ${index + 1}/${config.releaseNotes.descriptions.size}, " + "lang=${releaseNote.lang}" ) logger.i( @@ -266,11 +288,11 @@ open class HuaweiPublishTask ) } } else { - logger.v("Skip release notes uploading") + logger.v("6. Skip release notes uploading") } if (config.deployType != DeployType.UPLOAD_ONLY) { - logger.v("Update App File Info") + logger.v("7. Update App File Info") val fileInfoRequestList = mapFileInfo(fileInfoListResult, config.artifactFile.name) val appId = appInfo.value val releasePercent = config.releasePhase?.percent ?: FULL_USER_SUBMISSION_PERCENT @@ -301,7 +323,7 @@ open class HuaweiPublishTask } if (config.deployType == DeployType.PUBLISH) { - logger.v("Submit Review") + logger.v("8. Submit Review") val submitRequestFunction: () -> SubmitResponse = { getSubmitResponse( @@ -331,6 +353,7 @@ open class HuaweiPublishTask } else { logger.v("Upload build file without draft and submit on users - Successfully Done!") } + mockServerWrapper.shutdown() } @Suppress("LongParameterList") @@ -408,6 +431,18 @@ open class HuaweiPublishTask return fileInfoRequestList } + private fun getMockServerWrapper( + config: HuaweiPublishConfig, + ): MockServerWrapper { + return if (apiStub == true) { + MockServerWrapperImpl( + logger = logger, + ) + } else { + MockServerWrapperStub() + } + } + internal enum class ReleaseType(val type: Int) { FULL(type = 1), PHASE(type = 3) diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/service/HuaweiServiceImpl.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/service/HuaweiServiceImpl.kt index c8ffb8e..52066b1 100644 --- a/plugin/src/main/kotlin/ru/cian/huawei/publish/service/HuaweiServiceImpl.kt +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/service/HuaweiServiceImpl.kt @@ -26,20 +26,17 @@ import ru.cian.huawei.publish.service.HttpClientHelper.Companion.MEDIA_TYPE_AAB import ru.cian.huawei.publish.service.HttpClientHelper.Companion.MEDIA_TYPE_JSON import ru.cian.huawei.publish.utils.Logger -private const val DOMAIN_URL = "https://connect-api.cloud.huawei.com/api" -private const val PUBLISH_API_URL = "$DOMAIN_URL/publish/v2" -private const val GRANT_TYPE = "client_credentials" -private const val SUBMIT_LONG_PUBLICATION_ERROR = 204144660 -private const val SUBMIT_REPEAT_TIMEOUT_MS = 3 * 60 * 1000L // 3 min - @Suppress("StringLiteralDuplication", "TooManyFunctions") -internal class HuaweiServiceImpl constructor( - private val logger: Logger +internal class HuaweiServiceImpl( + private val logger: Logger, + private val baseEntryPoint: String, ) : HuaweiService { private val gson = Gson() private val httpClient = HttpClientHelper(logger) + private val PUBLISH_API_URL = "$baseEntryPoint/publish/v2" + override fun getToken( clientId: String, clientSecret: String @@ -52,7 +49,7 @@ internal class HuaweiServiceImpl constructor( ) val accessTokenResponse = httpClient.post( - url = "$DOMAIN_URL/oauth2/v1/token", + url = "$baseEntryPoint/oauth2/v1/token", body = gson.toJson(bodyRequest).toRequestBody(MEDIA_TYPE_JSON), headers = null, ) @@ -321,4 +318,11 @@ internal class HuaweiServiceImpl constructor( return result } + + companion object { + const val DOMAIN_URL = "https://connect-api.cloud.huawei.com/api" + private const val GRANT_TYPE = "client_credentials" + private const val SUBMIT_LONG_PUBLICATION_ERROR = 204144660 + private const val SUBMIT_REPEAT_TIMEOUT_MS = 3 * 60 * 1000L // 3 min + } } diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/service/MockHuaweiService.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/service/MockHuaweiService.kt deleted file mode 100644 index 2325354..0000000 --- a/plugin/src/main/kotlin/ru/cian/huawei/publish/service/MockHuaweiService.kt +++ /dev/null @@ -1,133 +0,0 @@ -package ru.cian.huawei.publish.service - -import org.gradle.internal.resource.transport.http.HttpRequestException -import ru.cian.huawei.publish.models.request.FileInfoRequest -import ru.cian.huawei.publish.models.response.AppInfo -import ru.cian.huawei.publish.models.response.FileServerOriResultResponse -import ru.cian.huawei.publish.models.response.Result -import ru.cian.huawei.publish.models.response.Ret -import ru.cian.huawei.publish.models.response.SubmitResponse -import ru.cian.huawei.publish.models.response.UpdateAppFileInfoResponse -import ru.cian.huawei.publish.models.response.UpdateAppBasicInfoResponse -import ru.cian.huawei.publish.models.response.UpdateReleaseNotesResponse -import ru.cian.huawei.publish.models.response.UploadFileRsp -import ru.cian.huawei.publish.models.response.UploadUrlResponse -import java.io.File - -private const val REQUEST_RETRIES = 5 - -@Suppress("StringLiteralDuplication", "TooManyFunctions") -internal class MockHuaweiService : HuaweiService { - - private var retries = 0 - - override fun getToken(clientId: String, clientSecret: String) = "MockToken" - - override fun getAppID( - clientId: String, - accessToken: String, - packageName: String - ) = AppInfo( - key = "MockKey", - value = "MockValue" - ) - - override fun getUploadingBuildUrl( - clientId: String, - accessToken: String, - appId: String, - suffix: String - ) = UploadUrlResponse( - ret = Ret( - code = -1, - msg = "MockMessage" - ), - uploadUrl = "MockUploadUrl", - chunkUploadUrl = "MockChunkUploadUrl", - authCode = "MockAuthCode" - ) - - override fun uploadBuildFile( - uploadUrl: String, - authCode: String, - buildFile: File - ) = FileServerOriResultResponse( - result = Result( - resultCode = -1, - uploadFileRsp = UploadFileRsp( - ifSuccess = 1, - fileInfoList = emptyList() - ) - ) - ) - - override fun updateAppFileInformation( - clientId: String, - accessToken: String, - appId: String, - releaseType: Int, - fileInfoRequestList: List - ) = UpdateAppFileInfoResponse( - ret = Ret( - code = -1, - msg = "MockMessage" - ) - ) - - override fun updateReleaseNotes( - clientId: String, - accessToken: String, - appId: String, - lang: String, - newFeatures: String - ) = UpdateReleaseNotesResponse( - ret = Ret( - code = -1, - msg = "MockMessage" - ) - ) - - override fun submitReviewImmediately( - clientId: String, - accessToken: String, - appId: String, - releaseTime: String? - ) = getSubmitResponseWithRetries() - - override fun submitReviewWithReleasePhase( - clientId: String, - accessToken: String, - appId: String, - startRelease: String?, - endRelease: String?, - releasePercent: Double - ) = getSubmitResponseWithRetries() - - override fun updateAppBasicInfo( - clientId: String, - accessToken: String, - appId: String, - releaseType: Int, - appBasicInfo: String - ) = UpdateAppBasicInfoResponse( - ret = Ret( - code = -1, - msg = "MockMessage" - ) - ) - - @Suppress("ThrowingExceptionsWithoutMessageOrCause") - private fun getSubmitResponseWithRetries(): SubmitResponse { - if (retries < REQUEST_RETRIES) { - retries++ - throw HttpRequestException("That's work as well for MockServer, attempt=$retries", Throwable()) - } else { - return SubmitResponse( - ret = Ret( - code = -1, - msg = "MockMessage" - ) - ) - } - } -} diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/service/mock/MockServerWrapper.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/service/mock/MockServerWrapper.kt new file mode 100644 index 0000000..71b72c6 --- /dev/null +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/service/mock/MockServerWrapper.kt @@ -0,0 +1,10 @@ +package ru.cian.huawei.publish.service.mock + +interface MockServerWrapper { + + fun getBaseUrl(): String + + fun start() + + fun shutdown() +} \ No newline at end of file diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/service/mock/MockServerWrapperImpl.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/service/mock/MockServerWrapperImpl.kt new file mode 100644 index 0000000..378a588 --- /dev/null +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/service/mock/MockServerWrapperImpl.kt @@ -0,0 +1,157 @@ +package ru.cian.huawei.publish.service.mock + +import okhttp3.mockwebserver.Dispatcher +import okhttp3.mockwebserver.MockResponse +import okhttp3.mockwebserver.MockWebServer +import okhttp3.mockwebserver.RecordedRequest +import ru.cian.huawei.publish.utils.Logger +import java.util.concurrent.TimeUnit + +private const val DELAY_REQUEST_BODY_SECONDS = 2L + +@SuppressWarnings("MaxLineLength", "MagicNumber") +class MockServerWrapperImpl( + val logger: Logger, +): MockServerWrapper { + + private lateinit var mockWebServer: MockWebServer + + override fun getBaseUrl(): String { + return mockWebServer.url("/").toString() + } + + override fun start() { + logger.v(":: start mock server") + + mockWebServer = MockWebServer() + mockWebServer.start() + + val dispatcher = object : Dispatcher() { + @Throws(InterruptedException::class) + @SuppressWarnings("ReturnCount") + override fun dispatch(request: RecordedRequest): MockResponse { + when { + request.path!!.contains("/oauth2/v1/token") -> return MockResponse() + .setResponseCode(200) + .setBodyDelay(DELAY_REQUEST_BODY_SECONDS, TimeUnit.SECONDS) + .setBody( + """{ + "access_token": "abcd1234token", + "expires_in": 3600, + "ret": { + "code": 0, + "msg": "Success" + } + }""".trimMargin()) + request.path!!.contains("/appid-list") -> return MockResponse() + .setResponseCode(200) + .setBodyDelay(DELAY_REQUEST_BODY_SECONDS, TimeUnit.SECONDS) + .setBody( + """{ + "ret": { + "code": 0, + "msg": "Success" + }, + "appids": [ + { + "key": "app1", + "value": "App One" + }, + { + "key": "app2", + "value": "App Two" + } + ] + }""".trimMargin()) + request.path!!.contains("/upload-url") -> return MockResponse() + .setResponseCode(200) + .setBodyDelay(DELAY_REQUEST_BODY_SECONDS, TimeUnit.SECONDS) + .setBody( + """{ + "ret": { + "code": 0, + "msg": "Success" + }, + "uploadUrl": "${getBaseUrl()}/upload_file_stub", + "chunkUploadUrl": "${getBaseUrl()}/upload/chunk_stub", + "authCode": "abc123securetoken" + } + """.trimMargin()) + request.path!!.contains("/upload_file_stub") -> return MockResponse() + .setResponseCode(200) + .setBodyDelay(DELAY_REQUEST_BODY_SECONDS, TimeUnit.SECONDS) + .setBody( + """{ + "result": { + "resultCode": 0, + "UploadFileRsp": { + "ifSuccess": 1, + "fileInfoList": [ + { + "fileDestUlr": "https://example.com/files/file1.jpg", + "imageResolution": "1920x1080", + "imageResolutionSingature": "signature123", + "size": 2048 + }, + { + "fileDestUlr": "https://example.com/files/file2.jpg", + "imageResolution": "1280x720", + "imageResolutionSingature": "signature456", + "size": 1024 + } + ] + } + } + }""".trimMargin()) + request.path!!.contains("/app-file-info") -> return MockResponse() + .setResponseCode(200) + .setBodyDelay(DELAY_REQUEST_BODY_SECONDS, TimeUnit.SECONDS) + .setBody( + """{ + "ret": { + "code": 0, + "msg": "Success" + } + }""".trimMargin()) + request.path!!.contains("/app-language-info") -> return MockResponse() + .setResponseCode(200) + .setBodyDelay(DELAY_REQUEST_BODY_SECONDS, TimeUnit.SECONDS) + .setBody( + """{ + "ret": { + "code": 0, + "msg": "Success" + } + }""".trimMargin()) + request.path!!.contains("/app-submit") -> return MockResponse() + .setResponseCode(200) + .setBodyDelay(DELAY_REQUEST_BODY_SECONDS, TimeUnit.SECONDS) + .setBody( + """{ + "ret": { + "code": 0, + "msg": "Success" + } + }""".trimMargin()) + request.path!!.contains("/app-info") -> return MockResponse() + .setResponseCode(200) + .setBodyDelay(DELAY_REQUEST_BODY_SECONDS, TimeUnit.SECONDS) + .setBody( + """{ + "ret": { + "code": 0, + "msg": "Success" + } + }""".trimMargin()) + } + return MockResponse().setResponseCode(404) + } + } + mockWebServer.dispatcher = dispatcher + } + + override fun shutdown() { + logger.v(":: shutdown mock server") + mockWebServer.shutdown() + } +} \ No newline at end of file diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/service/mock/MockServerWrapperStub.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/service/mock/MockServerWrapperStub.kt new file mode 100644 index 0000000..a211406 --- /dev/null +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/service/mock/MockServerWrapperStub.kt @@ -0,0 +1,18 @@ +package ru.cian.huawei.publish.service.mock + +import ru.cian.huawei.publish.service.HuaweiServiceImpl + +class MockServerWrapperStub : MockServerWrapper { + + override fun getBaseUrl(): String { + return HuaweiServiceImpl.DOMAIN_URL + } + + override fun start() { + // nothing; + } + + override fun shutdown() { + // nothing; + } +} \ No newline at end of file diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/BuildFileProvider.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/BuildFileProvider.kt index b2107db..e4d1204 100644 --- a/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/BuildFileProvider.kt +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/BuildFileProvider.kt @@ -1,35 +1,9 @@ package ru.cian.huawei.publish.utils -import com.android.build.api.artifact.SingleArtifact -import com.android.build.api.variant.ApplicationVariant import ru.cian.huawei.publish.BuildFormat import java.io.File -internal class BuildFileProvider( - private val variant: ApplicationVariant, - private val logger: Logger, -) { +internal interface BuildFileProvider { - fun getBuildFile(buildFormat: BuildFormat): File? { - return when (buildFormat) { - BuildFormat.APK -> getFinalApkArtifactCompat(variant).singleOrNull() - BuildFormat.AAB -> getFinalBundleArtifactCompat(variant).singleOrNull() - } - } - - // TODO(a.mirko): Remove after https://github.com/gradle/gradle/issues/16777 - // TODO(a.mirko): Remove after https://github.com/gradle/gradle/issues/16775 - private fun getFinalApkArtifactCompat(variant: ApplicationVariant): List { - val apkDirectory = variant.artifacts.get(SingleArtifact.APK).get() - logger.v("Build File Directory: $apkDirectory") - return variant.artifacts.getBuiltArtifactsLoader().load(apkDirectory) - ?.elements?.map { element -> File(element.outputFile) } - ?: apkDirectory.asFileTree.matching { include("*.apk") }.map { it.absolutePath }.map { File(it) } - ?: emptyList() - } - - private fun getFinalBundleArtifactCompat(variant: ApplicationVariant): List { - val aabFile = variant.artifacts.get(SingleArtifact.BUNDLE).get().asFile - return listOf(aabFile) - } + fun getBuildFile(buildFormat: BuildFormat): File? } diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/BuildFileProviderDeprecated.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/BuildFileProviderDeprecated.kt new file mode 100644 index 0000000..57c08c1 --- /dev/null +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/BuildFileProviderDeprecated.kt @@ -0,0 +1,35 @@ +package ru.cian.huawei.publish.utils + +import com.android.build.api.artifact.SingleArtifact +import com.android.build.api.variant.ApplicationVariant +import ru.cian.huawei.publish.BuildFormat +import java.io.File + +internal class BuildFileProviderDeprecated( + private val variant: ApplicationVariant, + private val logger: Logger, +) : BuildFileProvider { + + override fun getBuildFile(buildFormat: BuildFormat): File? { + return when (buildFormat) { + BuildFormat.APK -> getFinalApkArtifactCompat(variant).singleOrNull() + BuildFormat.AAB -> getFinalBundleArtifactCompat(variant).singleOrNull() + } + } + + // TODO(a.mirko): Remove after https://github.com/gradle/gradle/issues/16777 + // TODO(a.mirko): Remove after https://github.com/gradle/gradle/issues/16775 + private fun getFinalApkArtifactCompat(variant: ApplicationVariant): List { + val apkDirectory = variant.artifacts.get(SingleArtifact.APK).get() + logger.v("Build File Directory: $apkDirectory") + return variant.artifacts.getBuiltArtifactsLoader().load(apkDirectory) + ?.elements?.map { element -> File(element.outputFile) } + ?: apkDirectory.asFileTree.matching { include("*.apk") }.map { it.absolutePath }.map { File(it) } + ?: emptyList() + } + + private fun getFinalBundleArtifactCompat(variant: ApplicationVariant): List { + val aabFile = variant.artifacts.get(SingleArtifact.BUNDLE).get().asFile + return listOf(aabFile) + } +} diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/BuildFileProviderNew.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/BuildFileProviderNew.kt new file mode 100644 index 0000000..7fb1333 --- /dev/null +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/BuildFileProviderNew.kt @@ -0,0 +1,36 @@ +package ru.cian.huawei.publish.utils + +import com.android.build.api.artifact.SingleArtifact +import com.android.build.api.variant.ApplicationVariant +import ru.cian.huawei.publish.BuildFormat +import java.io.File + +internal class BuildFileProviderNew( + private val variantApkBuildFilePath: String?, + private val variantAabBuildFilePath: String?, + private val logger: Logger, +) : BuildFileProvider { + + override fun getBuildFile(buildFormat: BuildFormat): File? { + return when (buildFormat) { + BuildFormat.APK -> variantApkBuildFilePath?.let { File(it) } + BuildFormat.AAB -> variantAabBuildFilePath?.let { File(it) } + } + } + + // TODO(a.mirko): Remove after https://github.com/gradle/gradle/issues/16777 + // TODO(a.mirko): Remove after https://github.com/gradle/gradle/issues/16775 + private fun getFinalApkArtifactCompat(variant: ApplicationVariant): List { + val apkDirectory = variant.artifacts.get(SingleArtifact.APK).get() + logger.v("Build File Directory: $apkDirectory") + return variant.artifacts.getBuiltArtifactsLoader().load(apkDirectory) + ?.elements?.map { element -> File(element.outputFile) } + ?: apkDirectory.asFileTree.matching { include("*.apk") }.map { it.absolutePath }.map { File(it) } + ?: emptyList() + } + + private fun getFinalBundleArtifactCompat(variant: ApplicationVariant): List { + val aabFile = variant.artifacts.get(SingleArtifact.BUNDLE).get().asFile + return listOf(aabFile) + } +} diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/Logger.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/Logger.kt index 67b1fab..5d69718 100644 --- a/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/Logger.kt +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/Logger.kt @@ -5,7 +5,7 @@ import org.gradle.api.Project private const val LOG_TAG = "Huawei AppGallery Publishing API" -internal class Logger constructor( +class Logger constructor( private val project: Project ) { From 702190c3eb99546977ecfa5e6f76ba5e076bce96 Mon Sep 17 00:00:00 2001 From: Aleksandr Mirko Date: Sun, 6 Oct 2024 13:11:20 +0100 Subject: [PATCH 4/9] Update Gradle and AGP versions --- gradle/libs.versions.toml | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 60f85cf..91f5936 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -12,7 +12,7 @@ jvm = "17" kotlin = "1.9.22" detekt = "1.23.4" junitJupiter = "5.9.3" -androidGradlePlugin = "8.2.0" +androidGradlePlugin = "8.6.0" sampleHuaweiPlugin = "1.4.3-alpha01" [libraries] diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 564b973..2177217 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-all.zip From 3401bb6c390a5dcaf30da9a0e1e121a754bc3940 Mon Sep 17 00:00:00 2001 From: Aleksandr Mirko Date: Mon, 7 Oct 2024 23:44:23 +0100 Subject: [PATCH 5/9] #58 Add param to change the socket timeout for publish requests in seconds --- CHANGELOG.md | 3 +++ README.md | 10 ++++++++++ gradle/libs.versions.toml | 2 +- plugin/gradle.properties | 2 +- .../ru/cian/huawei/publish/HuaweiPublishConfig.kt | 2 ++ .../cian/huawei/publish/HuaweiPublishExtension.kt | 3 +++ .../ru/cian/huawei/publish/HuaweiPublishTask.kt | 9 +++++++++ .../publish/models/request/FileInfoRequest.kt | 2 +- .../cian/huawei/publish/models/response/FileInfo.kt | 2 +- .../cian/huawei/publish/service/HttpClientHelper.kt | 13 ++++++++++--- .../huawei/publish/service/HuaweiServiceImpl.kt | 3 ++- .../publish/service/mock/MockServerWrapperImpl.kt | 2 +- .../ru/cian/huawei/publish/utils/ConfigProvider.kt | 2 ++ .../cian/huawei/publish/utils/ConfigProviderTest.kt | 6 ++++++ sample-groovy/build.gradle | 1 + sample-kotlin/build.gradle.kts | 1 + 16 files changed, 54 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9080340..9c812b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # 1.4.3 +##### Add +* [issue#58] Add `publishSocketTimeoutInSeconds` param to change the socket timeout for publish requests in seconds. + ##### Breaking Changes * Remove support of Sonatype. It means that you can't use the plugin from Maven Central. You must to use the Gradle Portal. To do this, you need to add the following code to your `settings.gradle.kts`: diff --git a/README.md b/README.md index 8d5302c..0d0d9e0 100644 --- a/README.md +++ b/README.md @@ -204,6 +204,14 @@ huaweiPublish { */ buildFormat = ru.cian.huawei.publish.BuildFormat.APK + /** + * The socket timeout for publish requests in seconds. + * Type: Long (Optional) + * Default value: `60` // (1min) + * CLI: `--publishSocketTimeoutInSeconds` + */ + publishSocketTimeoutInSeconds = 60 + /** * API use chunks to upload the build file. So after last file part server needs some time to join and check whole file. * This param provide time in millis during which the plugin periodically tries to publish the build. @@ -337,6 +345,7 @@ huaweiPublish { credentialsPath = "$rootDir/huawei-credentials-release.json" deployType = "publish" buildFormat = "apk" + publishSocketTimeoutInSeconds = 60 publishTimeoutMs = 600_000 publishPeriodMs = 15_000 releaseTime = "2025-10-21T06:00:00+0300" @@ -412,6 +421,7 @@ CLI params are more priority than gradle configuration params. --credentialsPath="/sample-kotlin/huawei-credentials.json" \ --deployType=publish \ --buildFormat=apk \ + --publishSocketTimeoutInSeconds=60 \ --publishTimeoutMs=600000 \ --publishPeriodMs=15000 \ --releaseTime="2025-10-21T06:00:00+0300" \ diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 91f5936..bc13419 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,7 @@ kotlin = "1.9.22" detekt = "1.23.4" junitJupiter = "5.9.3" androidGradlePlugin = "8.6.0" -sampleHuaweiPlugin = "1.4.3-alpha01" +sampleHuaweiPlugin = "1.4.3-alpha02" [libraries] appcompat = "androidx.appcompat:appcompat:1.6.1" diff --git a/plugin/gradle.properties b/plugin/gradle.properties index a8e2322..0fb9fba 100644 --- a/plugin/gradle.properties +++ b/plugin/gradle.properties @@ -9,7 +9,7 @@ android.enableJetifier=true #################################################################################################### GROUP=ru.cian -VERSION_NAME=1.4.3-alpha01 +VERSION_NAME=1.4.3-alpha02 REQUIRED_JDK_VERSION=17 diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishConfig.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishConfig.kt index f90b611..c3f17c7 100644 --- a/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishConfig.kt +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishConfig.kt @@ -9,6 +9,7 @@ internal data class HuaweiPublishConfig( val artifactFile: File, val publishTimeoutMs: Long, val publishPeriodMs: Long, + val publishSocketTimeoutInSeconds: Long, val releaseTime: String?, val releasePhase: ReleasePhaseConfig?, val releaseNotes: ReleaseNotesConfig?, @@ -30,6 +31,7 @@ internal data class HuaweiPublishCliParam( val deployType: DeployType? = null, val publishTimeoutMs: String? = null, val publishPeriodMs: String? = null, + val publishSocketTimeoutInSeconds: String? = null, val credentialsPath: String? = null, val clientId: String? = null, val clientSecret: String? = null, diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishExtension.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishExtension.kt index 64fb8fc..73b105c 100644 --- a/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishExtension.kt +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishExtension.kt @@ -3,6 +3,7 @@ package ru.cian.huawei.publish import groovy.lang.Closure import org.gradle.api.Project +private const val DEFAULT_PUBLISH_SOCKET_TIMEOUT_IN_SECONDS = 60L private const val DEFAULT_PUBLISH_TIMEOUT_MS = 10 * 60 * 1000L private const val DEFAULT_PUBLISH_PERIOD_MS = 15 * 1000L @@ -34,6 +35,7 @@ class HuaweiPublishExtensionConfig( var deployType = DeployType.PUBLISH var publishTimeoutMs: Long = DEFAULT_PUBLISH_TIMEOUT_MS var publishPeriodMs: Long = DEFAULT_PUBLISH_PERIOD_MS + var publishSocketTimeoutInSeconds: Long = DEFAULT_PUBLISH_SOCKET_TIMEOUT_IN_SECONDS var buildFormat: BuildFormat = BuildFormat.APK var buildFile: String? = null var releaseTime: String? = null @@ -66,6 +68,7 @@ class HuaweiPublishExtensionConfig( "deployType='$deployType', " + "publishTimeoutMs='$publishTimeoutMs', " + "publishPeriodMs='$publishPeriodMs', " + + "publishSocketTimeoutInSeconds='$publishSocketTimeoutInSeconds', " + "buildFormat='$buildFormat', " + "buildFile='$buildFile', " + "releaseTime='$releaseTime', " + diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishTask.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishTask.kt index 2526a49..3080f61 100644 --- a/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishTask.kt +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishTask.kt @@ -76,6 +76,13 @@ open class HuaweiPublishTask ) var publishPeriodMs: String? = null + @get:Internal + @set:Option( + option = "publishSocketTimeoutInSeconds", + description = "The socket timeout for publish requests in seconds" + ) + var publishSocketTimeoutInSeconds: String? = null + @get:Internal @set:Option( option = "credentialsPath", @@ -190,6 +197,7 @@ open class HuaweiPublishTask deployType = deployType, publishTimeoutMs = publishTimeoutMs, publishPeriodMs = publishPeriodMs, + publishSocketTimeoutInSeconds = publishSocketTimeoutInSeconds, credentialsPath = credentialsPath, clientId = clientId, clientSecret = clientSecret, @@ -232,6 +240,7 @@ open class HuaweiPublishTask val huaweiService = HuaweiServiceImpl( logger=logger, baseEntryPoint=mockServerWrapper.getBaseUrl(), + publishSocketTimeoutInSeconds=config.publishSocketTimeoutInSeconds, ) logger.v("2. Get Access Token") diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/models/request/FileInfoRequest.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/models/request/FileInfoRequest.kt index 1c5732f..8ae3ab3 100644 --- a/plugin/src/main/kotlin/ru/cian/huawei/publish/models/request/FileInfoRequest.kt +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/models/request/FileInfoRequest.kt @@ -8,5 +8,5 @@ internal data class FileInfoRequest( @SerializedName("fileDestUrl") var fileDestUrl: String, @SerializedName("size") - var size: Int + var size: Long ) diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/models/response/FileInfo.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/models/response/FileInfo.kt index a254ebb..0fde729 100644 --- a/plugin/src/main/kotlin/ru/cian/huawei/publish/models/response/FileInfo.kt +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/models/response/FileInfo.kt @@ -10,5 +10,5 @@ internal data class FileInfo( @SerializedName("imageResolutionSingature") var imageResolutionSignature: String, @SerializedName("size") - var size: Int + var size: Long ) diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/service/HttpClientHelper.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/service/HttpClientHelper.kt index 8056a71..220f1fe 100644 --- a/plugin/src/main/kotlin/ru/cian/huawei/publish/service/HttpClientHelper.kt +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/service/HttpClientHelper.kt @@ -7,9 +7,11 @@ import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.RequestBody import ru.cian.huawei.publish.utils.Logger +import java.util.concurrent.TimeUnit -internal class HttpClientHelper constructor( - private val logger: Logger +internal class HttpClientHelper( + private val logger: Logger, + private val socketTimeoutInSeconds: Long, ) { private val gson by lazy { Gson() } @@ -26,7 +28,12 @@ internal class HttpClientHelper constructor( @Suppress("ThrowsCount") inline fun execute(requestBuilder: Request.Builder, url: String, headers: Map?): T { try { - val client = OkHttpClient() + val client = OkHttpClient.Builder() + .connectTimeout(socketTimeoutInSeconds, TimeUnit.SECONDS) + .writeTimeout(socketTimeoutInSeconds, TimeUnit.SECONDS) + .readTimeout(socketTimeoutInSeconds, TimeUnit.SECONDS) + .build() + val request = requestBuilder .url(url) .apply { headers?.forEach { header(it.key, it.value) } } diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/service/HuaweiServiceImpl.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/service/HuaweiServiceImpl.kt index 52066b1..209c728 100644 --- a/plugin/src/main/kotlin/ru/cian/huawei/publish/service/HuaweiServiceImpl.kt +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/service/HuaweiServiceImpl.kt @@ -30,10 +30,11 @@ import ru.cian.huawei.publish.utils.Logger internal class HuaweiServiceImpl( private val logger: Logger, private val baseEntryPoint: String, + private val publishSocketTimeoutInSeconds: Long, ) : HuaweiService { private val gson = Gson() - private val httpClient = HttpClientHelper(logger) + private val httpClient = HttpClientHelper(logger, publishSocketTimeoutInSeconds) private val PUBLISH_API_URL = "$baseEntryPoint/publish/v2" diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/service/mock/MockServerWrapperImpl.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/service/mock/MockServerWrapperImpl.kt index 378a588..f4e087d 100644 --- a/plugin/src/main/kotlin/ru/cian/huawei/publish/service/mock/MockServerWrapperImpl.kt +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/service/mock/MockServerWrapperImpl.kt @@ -7,7 +7,7 @@ import okhttp3.mockwebserver.RecordedRequest import ru.cian.huawei.publish.utils.Logger import java.util.concurrent.TimeUnit -private const val DELAY_REQUEST_BODY_SECONDS = 2L +private const val DELAY_REQUEST_BODY_SECONDS = 1L @SuppressWarnings("MaxLineLength", "MagicNumber") class MockServerWrapperImpl( diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/ConfigProvider.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/ConfigProvider.kt index d9c2d2f..d05ed37 100644 --- a/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/ConfigProvider.kt +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/ConfigProvider.kt @@ -26,6 +26,7 @@ internal class ConfigProvider( val deployType = cli.deployType ?: extension.deployType val publishTimeoutMs = cli.publishTimeoutMs?.toLong() ?: extension.publishTimeoutMs val publishPeriodMs = cli.publishPeriodMs?.toLong() ?: extension.publishPeriodMs + val publishSocketTimeoutInSeconds = cli.publishSocketTimeoutInSeconds?.toLong() ?: extension.publishSocketTimeoutInSeconds val artifactFormat = cli.buildFormat ?: extension.buildFormat val customBuildFilePath: String? = cli.buildFile ?: extension.buildFile val releaseTime: String? = cli.releaseTime ?: extension.releaseTime @@ -53,6 +54,7 @@ internal class ConfigProvider( artifactFile = artifactFile, publishTimeoutMs = publishTimeoutMs, publishPeriodMs = publishPeriodMs, + publishSocketTimeoutInSeconds = publishSocketTimeoutInSeconds, releaseTime = releaseTime, releasePhase = releasePhase, releaseNotes = releaseNotes, diff --git a/plugin/src/test/kotlin/ru/cian/huawei/publish/utils/ConfigProviderTest.kt b/plugin/src/test/kotlin/ru/cian/huawei/publish/utils/ConfigProviderTest.kt index 904bd3e..f940da9 100644 --- a/plugin/src/test/kotlin/ru/cian/huawei/publish/utils/ConfigProviderTest.kt +++ b/plugin/src/test/kotlin/ru/cian/huawei/publish/utils/ConfigProviderTest.kt @@ -28,6 +28,7 @@ import ru.cian.huawei.publish.ReleaseNotesConfig import ru.cian.huawei.publish.ReleaseNotesExtension import ru.cian.huawei.publish.ReleaseNotesDescriptionsConfig +private const val DEFAULT_PUBLISH_SOCKET_TIMEOUT_IN_SECONDS = 60L private const val DEFAULT_PUBLISH_TIMEOUT_MS = 10 * 60 * 1000L private const val DEFAULT_PUBLISH_PERIOD_MS = 15 * 1000L private const val BUILD_DIRECTORY_PATH = "./build" @@ -139,6 +140,7 @@ internal class ConfigProviderTest { deployType = DeployType.PUBLISH, artifactFormat = BuildFormat.APK, artifactFile = File(ARTIFACT_APK_FILE_PATH), + publishSocketTimeoutInSeconds = DEFAULT_PUBLISH_SOCKET_TIMEOUT_IN_SECONDS, publishTimeoutMs = DEFAULT_PUBLISH_TIMEOUT_MS, publishPeriodMs = DEFAULT_PUBLISH_PERIOD_MS, releaseTime = null, @@ -185,6 +187,7 @@ internal class ConfigProviderTest { deployType = DeployType.DRAFT, artifactFormat = BuildFormat.AAB, artifactFile = File(ARTIFACT_AAB_FILE_SECOND_PATH), + publishSocketTimeoutInSeconds = 3003L, publishTimeoutMs = 1001L, publishPeriodMs = 2002L, releaseTime = "2019-10-18T21:00:00+0300", @@ -214,6 +217,7 @@ internal class ConfigProviderTest { } val inputCliConfig = HuaweiPublishCliParam( deployType = DeployType.DRAFT, + publishSocketTimeoutInSeconds = "3003", publishTimeoutMs = "1001", publishPeriodMs = "2002", credentialsPath = CREDENTIALS_FILE_SECOND_PATH, @@ -248,6 +252,7 @@ internal class ConfigProviderTest { deployType = DeployType.PUBLISH, artifactFormat = BuildFormat.APK, artifactFile = File(ARTIFACT_APK_FILE_PATH), + publishSocketTimeoutInSeconds = DEFAULT_PUBLISH_SOCKET_TIMEOUT_IN_SECONDS, publishTimeoutMs = DEFAULT_PUBLISH_TIMEOUT_MS, publishPeriodMs = DEFAULT_PUBLISH_PERIOD_MS, releaseTime = null, @@ -327,6 +332,7 @@ internal class ConfigProviderTest { deployType = DeployType.PUBLISH, artifactFormat = BuildFormat.APK, artifactFile = File(ARTIFACT_APK_FILE_PATH), + publishSocketTimeoutInSeconds = DEFAULT_PUBLISH_SOCKET_TIMEOUT_IN_SECONDS, publishTimeoutMs = DEFAULT_PUBLISH_TIMEOUT_MS, publishPeriodMs = DEFAULT_PUBLISH_PERIOD_MS, releaseTime = null, diff --git a/sample-groovy/build.gradle b/sample-groovy/build.gradle index 0fbadf9..c96045a 100644 --- a/sample-groovy/build.gradle +++ b/sample-groovy/build.gradle @@ -24,6 +24,7 @@ huaweiPublish { credentialsPath = "$projectDir/huawei-credentials-2.json" deployType = "publish" buildFormat = "aab" + publishSocketTimeoutInSeconds = 60 publishTimeoutMs = 15_000 publishPeriodMs = 3_000 releaseTime = "2025-10-21T06:00:00+0300" diff --git a/sample-kotlin/build.gradle.kts b/sample-kotlin/build.gradle.kts index 291fa2f..48459df 100644 --- a/sample-kotlin/build.gradle.kts +++ b/sample-kotlin/build.gradle.kts @@ -10,6 +10,7 @@ huaweiPublish { credentialsPath = "$projectDir/huawei-credentials.json" deployType = ru.cian.huawei.publish.DeployType.DRAFT buildFormat = ru.cian.huawei.publish.BuildFormat.AAB + publishSocketTimeoutInSeconds = 60 publishTimeoutMs = 15_000 publishPeriodMs = 3_000 releaseTime = "2025-10-21T06:00:00+0300" From 2f0a76362d57be4fe8797b948dbe38dc914c77ed Mon Sep 17 00:00:00 2001 From: Aleksandr Mirko Date: Tue, 8 Oct 2024 21:29:49 +0100 Subject: [PATCH 6/9] #60 Add --buildFile param description to README --- README.md | 10 ++++++++++ .../kotlin/ru/cian/huawei/publish/HuaweiPublishTask.kt | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0d0d9e0..bc03430 100644 --- a/README.md +++ b/README.md @@ -203,6 +203,14 @@ huaweiPublish { * 'aab' – for AAB build format. */ buildFormat = ru.cian.huawei.publish.BuildFormat.APK + + /** + * Description: By default, the plugin searches for the assembly file at the standard file path. Use param to change file path. + * Type: String (Optional) + * Default value: null + * CLI: `--buildFile` + */ + buildFile = "${buildDir}/app/outputs/apk/release/app-release.apk" /** * The socket timeout for publish requests in seconds. @@ -345,6 +353,7 @@ huaweiPublish { credentialsPath = "$rootDir/huawei-credentials-release.json" deployType = "publish" buildFormat = "apk" + buildFile = "${buildDir}/app/outputs/apk/release/app-release.apk" publishSocketTimeoutInSeconds = 60 publishTimeoutMs = 600_000 publishPeriodMs = 15_000 @@ -421,6 +430,7 @@ CLI params are more priority than gradle configuration params. --credentialsPath="/sample-kotlin/huawei-credentials.json" \ --deployType=publish \ --buildFormat=apk \ + --buildFile="./app/outputs/apk/release/app-release.apk" --publishSocketTimeoutInSeconds=60 \ --publishTimeoutMs=600000 \ --publishPeriodMs=15000 \ diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishTask.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishTask.kt index 3080f61..64ad26e 100644 --- a/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishTask.kt +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishTask.kt @@ -116,7 +116,7 @@ open class HuaweiPublishTask @get:Internal @set:Option( option = "buildFile", - description = "Path to build file. 'null' means use standard path for 'apk' and 'aab' files." + description = "By default, the plugin searches for the assembly file at the standard file path. Use param to change file path." ) var buildFile: String? = null From 66df372ddf0758d08c1d3f69d1cacb8bce036805 Mon Sep 17 00:00:00 2001 From: Aleksandr Mirko Date: Tue, 8 Oct 2024 21:55:01 +0100 Subject: [PATCH 7/9] Fix detect --- plugin/config/detekt/detekt-config.yml | 2 +- .../huawei/publish/HuaweiPublishPlugin.kt | 9 +- .../cian/huawei/publish/HuaweiPublishTask.kt | 15 ++- .../publish/service/HuaweiServiceImpl.kt | 14 +-- .../service/mock/MockServerWrapperImpl.kt | 102 +++++++++++------- .../publish/utils/BuildFileProviderNew.kt | 1 + 6 files changed, 87 insertions(+), 56 deletions(-) diff --git a/plugin/config/detekt/detekt-config.yml b/plugin/config/detekt/detekt-config.yml index 5b3999f..7d747fc 100644 --- a/plugin/config/detekt/detekt-config.yml +++ b/plugin/config/detekt/detekt-config.yml @@ -100,7 +100,7 @@ formatting: active: false MaximumLineLength: active: true - maxLineLength: 120 + maxLineLength: 160 ignoreBackTickedIdentifier: true MultiLineIfElse: active: true diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishPlugin.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishPlugin.kt index 7800255..bd5134d 100644 --- a/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishPlugin.kt +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishPlugin.kt @@ -13,7 +13,6 @@ import org.gradle.kotlin.dsl.getByType import org.gradle.kotlin.dsl.register import org.gradle.kotlin.dsl.withType import java.io.File -import java.util.Optional class HuaweiPublishPlugin : Plugin { @@ -51,8 +50,8 @@ class HuaweiPublishPlugin : Plugin { // val variantApplicationId = variant.applicationId.get() // val variantApkBuildFilePath = getFinalApkArtifactCompat(variant).singleOrNull()?.absolutePath // val variantAabBuildFilePath = getFinalBundleArtifactCompat(variant).singleOrNull()?.absolutePath -//// val variantApkBuildFilePath = project.rootProject.path + "/app/build/outputs/bundle/release/app-release.aab" -//// val variantAabBuildFilePath = project.rootProject.path + "/app/build/outputs/apk/release/app-release.apk" +// // val variantApkBuildFilePath = project.rootProject.path + "/app/build/outputs/bundle/release/app-release.aab" +// // val variantAabBuildFilePath = project.rootProject.path + "/app/build/outputs/apk/release/app-release.apk" // val publishTaskName = "${HuaweiPublishTask.TASK_NAME}${variantName.capitalize()}" // val publishTask = project.tasks.register( // publishTaskName, @@ -61,7 +60,7 @@ class HuaweiPublishPlugin : Plugin { // Optional.ofNullable(variantApkBuildFilePath), // Optional.ofNullable(variantAabBuildFilePath), // ) -//// scheduleTasksOrder(publishTask, project, variantName) +// // scheduleTasksOrder(publishTask, project, variantName) } private fun scheduleTasksOrder( @@ -88,6 +87,7 @@ class HuaweiPublishPlugin : Plugin { // TODO(a.mirko): Remove after https://github.com/gradle/gradle/issues/16777 // TODO(a.mirko): Remove after https://github.com/gradle/gradle/issues/16775 + @SuppressWarnings("UnusedPrivateMember") private fun getFinalApkArtifactCompat(variant: ApplicationVariant): List { val apkDirectory = variant.artifacts.get(SingleArtifact.APK).get() return variant.artifacts.getBuiltArtifactsLoader().load(apkDirectory) @@ -96,6 +96,7 @@ class HuaweiPublishPlugin : Plugin { ?: emptyList() } + @SuppressWarnings("UnusedPrivateMember") private fun getFinalBundleArtifactCompat(variant: ApplicationVariant): List { val aabFile = variant.artifacts.get(SingleArtifact.BUNDLE).get().asFile return listOf(aabFile) diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishTask.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishTask.kt index 64ad26e..2368e85 100644 --- a/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishTask.kt +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishTask.kt @@ -116,7 +116,8 @@ open class HuaweiPublishTask @get:Internal @set:Option( option = "buildFile", - description = "By default, the plugin searches for the assembly file at the standard file path. Use param to change file path." + description = "By default, the plugin searches for the assembly file at the standard file path. " + + "Use param to change file path." ) var buildFile: String? = null @@ -234,13 +235,13 @@ open class HuaweiPublishTask logger.v("Found build file: `${config.artifactFile.name}`") - val mockServerWrapper = getMockServerWrapper(config=config) + val mockServerWrapper = getMockServerWrapper() mockServerWrapper.start() val huaweiService = HuaweiServiceImpl( - logger=logger, - baseEntryPoint=mockServerWrapper.getBaseUrl(), - publishSocketTimeoutInSeconds=config.publishSocketTimeoutInSeconds, + logger = logger, + baseEntryPoint = mockServerWrapper.getBaseUrl(), + publishSocketTimeoutInSeconds = config.publishSocketTimeoutInSeconds, ) logger.v("2. Get Access Token") @@ -440,9 +441,7 @@ open class HuaweiPublishTask return fileInfoRequestList } - private fun getMockServerWrapper( - config: HuaweiPublishConfig, - ): MockServerWrapper { + private fun getMockServerWrapper(): MockServerWrapper { return if (apiStub == true) { MockServerWrapperImpl( logger = logger, diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/service/HuaweiServiceImpl.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/service/HuaweiServiceImpl.kt index 209c728..477fbfc 100644 --- a/plugin/src/main/kotlin/ru/cian/huawei/publish/service/HuaweiServiceImpl.kt +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/service/HuaweiServiceImpl.kt @@ -36,7 +36,7 @@ internal class HuaweiServiceImpl( private val gson = Gson() private val httpClient = HttpClientHelper(logger, publishSocketTimeoutInSeconds) - private val PUBLISH_API_URL = "$baseEntryPoint/publish/v2" + private val publishEntryPoint = "$baseEntryPoint/publish/v2" override fun getToken( clientId: String, @@ -69,7 +69,7 @@ internal class HuaweiServiceImpl( headers["client_id"] = clientId val appIdResponse = httpClient.get( - url = "$PUBLISH_API_URL/appid-list?packageName=$packageName", + url = "$publishEntryPoint/appid-list?packageName=$packageName", headers = headers, ) if (appIdResponse.appids.isEmpty()) { @@ -90,7 +90,7 @@ internal class HuaweiServiceImpl( headers["client_id"] = clientId return httpClient.get( - url = "$PUBLISH_API_URL/upload-url?appId=$appId&suffix=$suffix", + url = "$publishEntryPoint/upload-url?appId=$appId&suffix=$suffix", headers = headers ) } @@ -144,7 +144,7 @@ internal class HuaweiServiceImpl( ) val result = httpClient.put( - url = "$PUBLISH_API_URL/app-file-info?appId=$appId&releaseType=$releaseType", + url = "$publishEntryPoint/app-file-info?appId=$appId&releaseType=$releaseType", body = gson.toJson(bodyRequest).toRequestBody(MEDIA_TYPE_JSON), headers = headers, ) @@ -174,7 +174,7 @@ internal class HuaweiServiceImpl( ) val result = httpClient.put( - url = "$PUBLISH_API_URL/app-language-info?appId=$appId", + url = "$publishEntryPoint/app-language-info?appId=$appId", body = gson.toJson(bodyRequest).toRequestBody(MEDIA_TYPE_JSON), headers = headers, ) @@ -276,7 +276,7 @@ internal class HuaweiServiceImpl( headers["client_id"] = clientId val result = httpClient.put( - url = "$PUBLISH_API_URL/app-info?appId=$appId&releaseType=$releaseType", + url = "$publishEntryPoint/app-info?appId=$appId&releaseType=$releaseType", body = appBasicInfo.toRequestBody(MEDIA_TYPE_JSON), headers = headers, ) @@ -302,7 +302,7 @@ internal class HuaweiServiceImpl( headers["Authorization"] = "Bearer $token" headers["client_id"] = clientId - val uriBuilder = "$PUBLISH_API_URL/app-submit".toHttpUrl() + val uriBuilder = "$publishEntryPoint/app-submit".toHttpUrl() .newBuilder() .addQueryParameter("appId", appId) .addQueryParameter("releaseType", releaseType.toString()) diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/service/mock/MockServerWrapperImpl.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/service/mock/MockServerWrapperImpl.kt index f4e087d..ed91d61 100644 --- a/plugin/src/main/kotlin/ru/cian/huawei/publish/service/mock/MockServerWrapperImpl.kt +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/service/mock/MockServerWrapperImpl.kt @@ -9,10 +9,10 @@ import java.util.concurrent.TimeUnit private const val DELAY_REQUEST_BODY_SECONDS = 1L -@SuppressWarnings("MaxLineLength", "MagicNumber") +@SuppressWarnings("MaxLineLength", "MagicNumber", "LongMethod") class MockServerWrapperImpl( val logger: Logger, -): MockServerWrapper { +) : MockServerWrapper { private lateinit var mockWebServer: MockWebServer @@ -35,19 +35,24 @@ class MockServerWrapperImpl( .setResponseCode(200) .setBodyDelay(DELAY_REQUEST_BODY_SECONDS, TimeUnit.SECONDS) .setBody( - """{ + """ + { "access_token": "abcd1234token", "expires_in": 3600, "ret": { "code": 0, "msg": "Success" } - }""".trimMargin()) + } + """.trimMargin() + ) + request.path!!.contains("/appid-list") -> return MockResponse() .setResponseCode(200) .setBodyDelay(DELAY_REQUEST_BODY_SECONDS, TimeUnit.SECONDS) .setBody( - """{ + """ + { "ret": { "code": 0, "msg": "Success" @@ -62,12 +67,16 @@ class MockServerWrapperImpl( "value": "App Two" } ] - }""".trimMargin()) + } + """.trimMargin() + ) + request.path!!.contains("/upload-url") -> return MockResponse() .setResponseCode(200) .setBodyDelay(DELAY_REQUEST_BODY_SECONDS, TimeUnit.SECONDS) .setBody( - """{ + """ + { "ret": { "code": 0, "msg": "Success" @@ -76,73 +85,94 @@ class MockServerWrapperImpl( "chunkUploadUrl": "${getBaseUrl()}/upload/chunk_stub", "authCode": "abc123securetoken" } - """.trimMargin()) + """.trimMargin() + ) + request.path!!.contains("/upload_file_stub") -> return MockResponse() .setResponseCode(200) .setBodyDelay(DELAY_REQUEST_BODY_SECONDS, TimeUnit.SECONDS) .setBody( - """{ - "result": { - "resultCode": 0, - "UploadFileRsp": { - "ifSuccess": 1, - "fileInfoList": [ - { - "fileDestUlr": "https://example.com/files/file1.jpg", - "imageResolution": "1920x1080", - "imageResolutionSingature": "signature123", - "size": 2048 - }, - { - "fileDestUlr": "https://example.com/files/file2.jpg", - "imageResolution": "1280x720", - "imageResolutionSingature": "signature456", - "size": 1024 + """ + { + "result": { + "resultCode": 0, + "UploadFileRsp": { + "ifSuccess": 1, + "fileInfoList": [ + { + "fileDestUlr": "https://example.com/files/file1.jpg", + "imageResolution": "1920x1080", + "imageResolutionSingature": "signature123", + "size": 2048 + }, + { + "fileDestUlr": "https://example.com/files/file2.jpg", + "imageResolution": "1280x720", + "imageResolutionSingature": "signature456", + "size": 1024 + } + ] } - ] + } } - } - }""".trimMargin()) + """.trimMargin() + ) + request.path!!.contains("/app-file-info") -> return MockResponse() .setResponseCode(200) .setBodyDelay(DELAY_REQUEST_BODY_SECONDS, TimeUnit.SECONDS) .setBody( - """{ + """ + { "ret": { "code": 0, "msg": "Success" } - }""".trimMargin()) + } + """.trimMargin() + ) + request.path!!.contains("/app-language-info") -> return MockResponse() .setResponseCode(200) .setBodyDelay(DELAY_REQUEST_BODY_SECONDS, TimeUnit.SECONDS) .setBody( - """{ + """ + { "ret": { "code": 0, "msg": "Success" } - }""".trimMargin()) + } + """.trimMargin() + ) + request.path!!.contains("/app-submit") -> return MockResponse() .setResponseCode(200) .setBodyDelay(DELAY_REQUEST_BODY_SECONDS, TimeUnit.SECONDS) .setBody( - """{ + """ + { "ret": { "code": 0, "msg": "Success" } - }""".trimMargin()) + } + """.trimMargin() + ) + request.path!!.contains("/app-info") -> return MockResponse() .setResponseCode(200) .setBodyDelay(DELAY_REQUEST_BODY_SECONDS, TimeUnit.SECONDS) .setBody( - """{ + """ + { "ret": { "code": 0, "msg": "Success" } - }""".trimMargin()) + } + """.trimMargin() + ) } return MockResponse().setResponseCode(404) } diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/BuildFileProviderNew.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/BuildFileProviderNew.kt index 7fb1333..2a877cb 100644 --- a/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/BuildFileProviderNew.kt +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/BuildFileProviderNew.kt @@ -5,6 +5,7 @@ import com.android.build.api.variant.ApplicationVariant import ru.cian.huawei.publish.BuildFormat import java.io.File +@SuppressWarnings("UnusedPrivateMember") internal class BuildFileProviderNew( private val variantApkBuildFilePath: String?, private val variantAabBuildFilePath: String?, From 24566e451bab5e8b347f8b9b86b17260a0fb870a Mon Sep 17 00:00:00 2001 From: Aleksandr Mirko Date: Sun, 13 Oct 2024 23:03:15 +0100 Subject: [PATCH 8/9] #59 Add new parameter to provide credentials as a base64 encoded string --- CHANGELOG.md | 4 +- README.md | 50 +++++-- .../huawei/publish/HuaweiPublishConfig.kt | 3 +- .../huawei/publish/HuaweiPublishExtension.kt | 2 + .../cian/huawei/publish/HuaweiPublishTask.kt | 26 ++-- .../huawei/publish/utils/ConfigProvider.kt | 31 ++++- .../huawei/publish/utils/CredentialHelper.kt | 7 +- .../publish/utils/ConfigProviderTest.kt | 129 +++++++++++++++--- sample-groovy/build.gradle | 1 + sample-kotlin/build.gradle.kts | 3 +- 10 files changed, 198 insertions(+), 58 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c812b8..89ef98f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # 1.4.3 ##### Add -* [issue#58] Add `publishSocketTimeoutInSeconds` param to change the socket timeout for publish requests in seconds. +* [issue#58] Add new `publishSocketTimeoutInSeconds` parameter to change the socket timeout for publish requests in seconds. +* [issue#59] Add new `credentials` parameter to provide credentials as a base64 encoded string. ##### Breaking Changes * Remove support of Sonatype. It means that you can't use the plugin from Maven Central. You must to use the Gradle Portal. @@ -13,6 +14,7 @@ } } ``` +* Remove support of `clientId` and `clientSecret` CLI params. Use `credentials` param instead. # 1.4.2 diff --git a/README.md b/README.md index bc03430..0e8cc31 100644 --- a/README.md +++ b/README.md @@ -109,19 +109,21 @@ huaweiPublish { instances { create("release") { /** - * Path to json file with AppGallery credentials params (`client_id` and `client_secret`). + * Description: The AppGallery credentials params (`client_id` and `client_secret`) in json format witch encoded to Base64. * How to get credentials see [AppGallery Connect API Getting Started](https://developer.huawei.com/consumer/en/doc/development/AppGallery-connect-Guides/agcapi-getstarted). - * Plugin credential json example: + * + * Credential json example: * { * "client_id": "", * "client_secret": "" * } + * Base64 encoded value example: "ewogICAgImNsaWVudF9pZCI6ICI8Q0xJRU5UX0lEPiIsCiAgICAiY2xpZW50X3NlY3JldCI6ICI8Q0xJRU5UX1NFQ1JFVD4iCn0=" * * Type: String (Optional) * Default value: `null` (but plugin wait that you provide credentials by CLI params) - * CLI: `--credentialsPath` - */ - credentialsPath = "$rootDir/huawei-credentials-release.json" + * CLI: `--credentials` + */ + credentials = "" /** * 'apk' or 'aab' for corresponding build format. @@ -160,9 +162,28 @@ huaweiPublish { huaweiPublish { instances { create("release") { + /** + * Description: The AppGallery credentials params (`client_id` and `client_secret`) in json format witch encoded to Base64. + * How to get credentials see [AppGallery Connect API Getting Started](https://developer.huawei.com/consumer/en/doc/development/AppGallery-connect-Guides/agcapi-getstarted). + * High priority than `credentialsPath` parameter. + * + * Credential json example: + * { + * "client_id": "", + * "client_secret": "" + * } + * Base64 encoded value example: "ewogICAgImNsaWVudF9pZCI6ICI8Q0xJRU5UX0lEPiIsCiAgICAiY2xpZW50X3NlY3JldCI6ICI8Q0xJRU5UX1NFQ1JFVD4iCn0=" + * + * Type: String (Optional) + * Default value: `null` (but plugin wait that you provide credentials by CLI params) + * CLI: `--credentials` + */ + credentials = "" + /** * Description: Path to json file with AppGallery credentials params (`client_id` and `client_secret`). * How to get credentials see [AppGallery Connect API Getting Started](https://developer.huawei.com/consumer/en/doc/development/AppGallery-connect-Guides/agcapi-getstarted). + * Low priority than `credentials` parameter. * * Plugin credential json example: * { @@ -350,7 +371,8 @@ huaweiPublish { huaweiPublish { instances { release { - credentialsPath = "$rootDir/huawei-credentials-release.json" + credentials = "" // High priority than `credentialsPath`; + credentialsPath = "$rootDir/huawei-credentials-release.json" // Low priority than `credentials`; deployType = "publish" buildFormat = "apk" buildFile = "${buildDir}/app/outputs/apk/release/app-release.apk" @@ -427,7 +449,8 @@ CLI params are more priority than gradle configuration params. ```bash ./gradlew assembleRelease publishHuaweiAppGalleryRelease \ - --credentialsPath="/sample-kotlin/huawei-credentials.json" \ + --credentials = "" \ # High priority than `credentialsPath`; + --credentialsPath="./sample-kotlin/huawei-credentials.json" \ # Low priority than `credentials`; --deployType=publish \ --buildFormat=apk \ --buildFile="./app/outputs/apk/release/app-release.apk" @@ -454,7 +477,7 @@ From gradle build script: huaweiPublish { instances { release { - credentialsPath = "$rootDir/sample1/huawei-credentials.json" + credentials = "" deployType = "draft" } } @@ -465,7 +488,7 @@ or execute from command line: ```bash ./gradlew assembleRelease publishHuaweiAppGalleryRelease \ - --credentialsPath="$rootDir/sample1/huawei-credentials.json" \ + --credentials = "" \ --deployType=draft ``` @@ -481,7 +504,7 @@ From gradle build script: huaweiPublish { instances { release { - credentialsPath = "$rootDir/sample1/huawei-credentials.json" + credentials = "" buildFormat = "aab" } } @@ -491,7 +514,7 @@ or execute from command line: ```bash ./gradlew assembleRelease publishHuaweiAppGalleryRelease \ - --credentialsPath="$rootDir/sample1/huawei-credentials.json" \ + --credentials = "" \ --buildFormat=aab ``` @@ -522,7 +545,7 @@ From gradle build script: huaweiPublish { instances { release { - credentialsPath = "$rootDir/sample1/huawei-credentials.json" + credentials = "" releasePhase { startTime = "2020-11-13T08:01:02+0300" endTime = "2020-11-20T15:30:00+0300" @@ -537,8 +560,7 @@ or execute from command line: ```bash ./gradlew assembleRelease publishHuaweiAppGalleryRelease \ - --clientId= \ - --clientSecret= \ + --credentials = "" \ --releasePhaseStartTime=2020-11-13T08:01:02+0300 \ --releasePhaseEndTime=2020-11-20T15:30:00+0300 \ --releasePhasePercent=10.0 diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishConfig.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishConfig.kt index c3f17c7..98d829a 100644 --- a/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishConfig.kt +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishConfig.kt @@ -32,9 +32,8 @@ internal data class HuaweiPublishCliParam( val publishTimeoutMs: String? = null, val publishPeriodMs: String? = null, val publishSocketTimeoutInSeconds: String? = null, + val credentials: String? = null, val credentialsPath: String? = null, - val clientId: String? = null, - val clientSecret: String? = null, val buildFormat: BuildFormat? = null, val buildFile: String? = null, val releaseTime: String? = null, diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishExtension.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishExtension.kt index 73b105c..86351df 100644 --- a/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishExtension.kt +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishExtension.kt @@ -31,6 +31,7 @@ class HuaweiPublishExtensionConfig( * For example: * var param by GradleProperty(project, String::class.java) */ + var credentials: String? = null var credentialsPath: String? = null var deployType = DeployType.PUBLISH var publishTimeoutMs: Long = DEFAULT_PUBLISH_TIMEOUT_MS @@ -64,6 +65,7 @@ class HuaweiPublishExtensionConfig( override fun toString(): String { return "HuaweiPublishExtensionConfig(" + "name='$name', " + + "credentials='$credentials', " + "credentialsPath='$credentialsPath', " + "deployType='$deployType', " + "publishTimeoutMs='$publishTimeoutMs', " + diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishTask.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishTask.kt index 2368e85..7e91682 100644 --- a/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishTask.kt +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/HuaweiPublishTask.kt @@ -85,26 +85,19 @@ open class HuaweiPublishTask @get:Internal @set:Option( - option = "credentialsPath", - description = "File path with AppGallery credentials params ('client_id' and 'client_secret')" - ) - var credentialsPath: String? = null - - @get:Internal - @set:Option( - option = "clientId", - description = "'client_id' param from AppGallery credentials. " + - "The key more priority than value from 'credentialsPath'" + option = "credentials", + description = "AppGallery credentials in Base64 format. " + + "Decoded json example: {\"client_id\": \"\", \"client_secret\": \"\"})" ) - var clientId: String? = null + var credentials: String? = null @get:Internal @set:Option( - option = "clientSecret", - description = "'client_secret' param from AppGallery credentials. " + - "The key more priority than value from 'credentialsPath'" + option = "credentialsPath", + description = "File path with AppGallery credentials params ('client_id' and 'client_secret') in json format. " + + "Json example: {\"client_id\": \"\", \"client_secret\": \"\"})" ) - var clientSecret: String? = null + var credentialsPath: String? = null @get:Internal @set:Option( @@ -199,9 +192,8 @@ open class HuaweiPublishTask publishTimeoutMs = publishTimeoutMs, publishPeriodMs = publishPeriodMs, publishSocketTimeoutInSeconds = publishSocketTimeoutInSeconds, + credentials = credentials, credentialsPath = credentialsPath, - clientId = clientId, - clientSecret = clientSecret, buildFormat = buildFormat, buildFile = buildFile, releaseTime = releaseTime, diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/ConfigProvider.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/ConfigProvider.kt index d05ed37..2b11b89 100644 --- a/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/ConfigProvider.kt +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/ConfigProvider.kt @@ -13,6 +13,8 @@ import ru.cian.huawei.publish.HuaweiPublishExtensionConfig import ru.cian.huawei.publish.ReleaseNotesConfig import ru.cian.huawei.publish.ReleaseNotesDescriptionsConfig import ru.cian.huawei.publish.ReleasePhaseConfig +import ru.cian.huawei.publish.models.Credential +import java.util.Base64 internal class ConfigProvider( private val extension: HuaweiPublishExtensionConfig, @@ -89,10 +91,17 @@ internal class ConfigProvider( @Suppress("ThrowsCount") fun getCredentialsConfig(): Credentials { + val credentialsBase64 = cli.credentials ?: extension.credentials + val credentialsFromBase64 = lazy { + if (credentialsBase64 != null) { + decodeCredentials(credentialsBase64) + } else { + null + } + } + val credentialsFilePath = cli.credentialsPath ?: extension.credentialsPath - val clientIdPriority: String? = cli.clientId - val clientSecretPriority: String? = cli.clientSecret - val credentials = lazy { + val credentialsResult = lazy { if (credentialsFilePath.isNullOrBlank()) { throw FileNotFoundException( "$extension (File path for credentials is null or empty. " + @@ -106,14 +115,17 @@ internal class ConfigProvider( "with 'client_id' and 'client_secret' for access to Huawei Publish API is not found)" ) } - CredentialHelper.getCredentials(credentialsFile) + CredentialHelper.getCredentialsFromFile(credentialsFile) } - val clientId = clientIdPriority ?: credentials.value.clientId.nullIfBlank() + + val clientId = credentialsFromBase64.value?.clientId + ?: credentialsResult.value.clientId.nullIfBlank() ?: throw IllegalArgumentException( "(Huawei credential `clientId` param is null or empty). " + "Please check your credentials file content or as single parameter." ) - val clientSecret = clientSecretPriority ?: credentials.value.clientSecret.nullIfBlank() + val clientSecret = credentialsFromBase64.value?.clientSecret + ?: credentialsResult.value.clientSecret.nullIfBlank() ?: throw IllegalArgumentException( "(Huawei credential `clientSecret` param is null or empty). " + "Please check your credentials file content or as single parameter." @@ -121,6 +133,13 @@ internal class ConfigProvider( return Credentials(clientId, clientSecret) } + @Throws(IllegalArgumentException::class) + fun decodeCredentials(encodedCredentials: String): Credential { + val decodedBytes = Base64.getDecoder().decode(encodedCredentials) + val decodedString = String(decodedBytes, Charsets.UTF_8) + return CredentialHelper.getCredentialsFromJson(decodedString) + } + @Suppress("ThrowsCount") fun getReleasePhaseConfig(): ReleasePhaseConfig? { val releasePhaseStartTime = cli.releasePhaseStartTime ?: extension.releasePhase?.startTime diff --git a/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/CredentialHelper.kt b/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/CredentialHelper.kt index 1dbbafc..dd45b27 100644 --- a/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/CredentialHelper.kt +++ b/plugin/src/main/kotlin/ru/cian/huawei/publish/utils/CredentialHelper.kt @@ -8,9 +8,14 @@ import java.io.File import java.io.FileReader internal object CredentialHelper { - fun getCredentials(credentialsFile: File): Credential { + fun getCredentialsFromFile(credentialsFile: File): Credential { val reader = JsonReader(FileReader(credentialsFile.absolutePath)) val type = object : TypeToken() {}.type return Gson().fromJson(reader, type) } + + fun getCredentialsFromJson(json: String): Credential { + val type = object : TypeToken() {}.type + return Gson().fromJson(json, type) + } } diff --git a/plugin/src/test/kotlin/ru/cian/huawei/publish/utils/ConfigProviderTest.kt b/plugin/src/test/kotlin/ru/cian/huawei/publish/utils/ConfigProviderTest.kt index f940da9..dad610c 100644 --- a/plugin/src/test/kotlin/ru/cian/huawei/publish/utils/ConfigProviderTest.kt +++ b/plugin/src/test/kotlin/ru/cian/huawei/publish/utils/ConfigProviderTest.kt @@ -1,7 +1,9 @@ package ru.cian.huawei.publish.utils +import assertk.assertFailure import assertk.assertThat import assertk.assertions.isEqualTo +import assertk.assertions.messageContains import assertk.tableOf import io.mockk.every import io.mockk.mockk @@ -21,7 +23,6 @@ import ru.cian.huawei.publish.HuaweiPublishConfig import ru.cian.huawei.publish.HuaweiPublishExtensionConfig import ru.cian.huawei.publish.ReleasePhaseConfig import ru.cian.huawei.publish.ReleasePhaseExtension -import ru.cian.huawei.publish.models.Credential import java.io.File import ru.cian.huawei.publish.ReleaseNote import ru.cian.huawei.publish.ReleaseNotesConfig @@ -50,6 +51,7 @@ private const val CREDENTIALS_SECOND_JSON = "{\"client_id\": \"no_id\", \"client private const val APP_BASIC_INFO_FILE_PATH = "$BUILD_DIRECTORY_PATH/app_info.json" private const val APP_BASIC_INFO_FILE_SECOND_PATH = "$BUILD_DIRECTORY_PATH/app_info_second.json" +@Suppress("LongMethod") @TestInstance(TestInstance.Lifecycle.PER_CLASS) internal class ConfigProviderTest { @@ -129,11 +131,12 @@ internal class ConfigProviderTest { releaseNotesFileProvider = releaseNotesFileProvider, ) - assertThat { configProvider.getConfig() }.hasException(IllegalArgumentException::class) + assertFailure { configProvider.getConfig() } + .messageContains("has wrong file extension that doesn't match with announced buildFormat(APK) plugin extension param") } @Test - fun `correct config for default params`() = mockkObject(CredentialHelper) { + fun `correct config with overriding credentials params`() = mockkObject(CredentialHelper) { val expectedConfig = HuaweiPublishConfig( credentials = Credentials("id", "secret"), @@ -149,11 +152,7 @@ internal class ConfigProviderTest { appBasicInfoFile = null ) - every { - CredentialHelper.getCredentials(match { it.absolutePath == CREDENTIALS_FILE_PATH }) - } returns Credential(clientId = "id", clientSecret = "secret") - - tableOf("expectedValue", "actualValue") + tableOf("expectedValue", "configProvider") .row( expectedConfig, ConfigProvider( @@ -164,18 +163,118 @@ internal class ConfigProviderTest { ) ) .row( - expectedConfig, + expectedConfig.copy( + credentials = Credentials("no_id", "no_secret") + ), + ConfigProvider( + extension = extensionConfigInstance().apply { + credentialsPath = CREDENTIALS_FILE_SECOND_PATH + }, + cli = emptyCliConfig, + buildFileProvider = buildFileProvider, + releaseNotesFileProvider = releaseNotesFileProvider, + ) + ) + .row( + expectedConfig.copy( + credentials = Credentials("no_id", "no_secret") + ), ConfigProvider( extension = extensionConfigInstance(), cli = HuaweiPublishCliParam( + credentialsPath = CREDENTIALS_FILE_SECOND_PATH + ), + buildFileProvider = buildFileProvider, + releaseNotesFileProvider = releaseNotesFileProvider, + ) + ) + .row( + expectedConfig.copy( + credentials = Credentials("no_id", "no_secret") + ), + ConfigProvider( + extension = extensionConfigInstance().apply { credentialsPath = CREDENTIALS_FILE_PATH + }, + cli = HuaweiPublishCliParam( + credentialsPath = CREDENTIALS_FILE_SECOND_PATH ), buildFileProvider = buildFileProvider, releaseNotesFileProvider = releaseNotesFileProvider, ) ) - .forAll { expectedValue, actualValue -> - assertThat(actualValue.getConfig()).isEqualTo(expectedValue) + .row( + expectedConfig.copy( + credentials = Credentials("id_base64", "secret_base64") + ), + ConfigProvider( + extension = extensionConfigInstance().apply { + credentials = "ewogICJjbGllbnRfaWQiOiAiaWRfYmFzZTY0IiwKICAiY2xpZW50X3NlY3JldCI6ICJzZWNyZXRfYmFzZTY0Igp9" + }, + cli = emptyCliConfig, + buildFileProvider = buildFileProvider, + releaseNotesFileProvider = releaseNotesFileProvider, + ) + ) + .row( + expectedConfig.copy( + credentials = Credentials("id_base64", "secret_base64") + ), + ConfigProvider( + extension = extensionConfigInstance(), + cli = HuaweiPublishCliParam( + credentials = "ewogICJjbGllbnRfaWQiOiAiaWRfYmFzZTY0IiwKICAiY2xpZW50X3NlY3JldCI6ICJzZWNyZXRfYmFzZTY0Igp9" + ), + buildFileProvider = buildFileProvider, + releaseNotesFileProvider = releaseNotesFileProvider, + ) + ) + .row( + expectedConfig.copy( + credentials = Credentials("id_base64", "secret_base64") + ), + ConfigProvider( + extension = extensionConfigInstance().apply { + credentials = "must_not_be_used" + }, + cli = HuaweiPublishCliParam( + credentials = "ewogICJjbGllbnRfaWQiOiAiaWRfYmFzZTY0IiwKICAiY2xpZW50X3NlY3JldCI6ICJzZWNyZXRfYmFzZTY0Igp9" + ), + buildFileProvider = buildFileProvider, + releaseNotesFileProvider = releaseNotesFileProvider, + ) + ) + .row( + expectedConfig.copy( + credentials = Credentials("id_base64", "secret_base64") + ), + ConfigProvider( + extension = extensionConfigInstance().apply { + credentials = "ewogICJjbGllbnRfaWQiOiAiaWRfYmFzZTY0IiwKICAiY2xpZW50X3NlY3JldCI6ICJzZWNyZXRfYmFzZTY0Igp9" + }, + cli = HuaweiPublishCliParam( + credentialsPath = CREDENTIALS_FILE_SECOND_PATH + ), + buildFileProvider = buildFileProvider, + releaseNotesFileProvider = releaseNotesFileProvider, + ) + ) + .row( + expectedConfig.copy( + credentials = Credentials("no_id", "no_secret") + ), + ConfigProvider( + extension = extensionConfigInstance().apply { + credentialsPath = CREDENTIALS_FILE_SECOND_PATH + }, + cli = emptyCliConfig, + buildFileProvider = buildFileProvider, + releaseNotesFileProvider = releaseNotesFileProvider, + ) + ) + .forAll { expectedValue, configProvider -> + val actualValue = configProvider.getConfig() + assertThat(actualValue).isEqualTo(expectedValue) } } @@ -183,7 +282,7 @@ internal class ConfigProviderTest { fun `correct config with overriding common values at cli params`() { val expectedConfig = HuaweiPublishConfig( - credentials = Credentials("id123", "secret123"), + credentials = Credentials("id_base64", "secret_base64"), deployType = DeployType.DRAFT, artifactFormat = BuildFormat.AAB, artifactFile = File(ARTIFACT_AAB_FILE_SECOND_PATH), @@ -201,7 +300,7 @@ internal class ConfigProviderTest { ) val inputExtensionConfig = extensionConfigInstance().apply { - credentialsPath = CREDENTIALS_FILE_PATH + credentialsPath = CREDENTIALS_FILE_SECOND_PATH deployType = DeployType.PUBLISH publishTimeoutMs = 3003 publishPeriodMs = 4004 @@ -216,13 +315,12 @@ internal class ConfigProviderTest { appBasicInfo = APP_BASIC_INFO_FILE_PATH } val inputCliConfig = HuaweiPublishCliParam( + credentials = "ewogICJjbGllbnRfaWQiOiAiaWRfYmFzZTY0IiwKICAiY2xpZW50X3NlY3JldCI6ICJzZWNyZXRfYmFzZTY0Igp9", deployType = DeployType.DRAFT, publishSocketTimeoutInSeconds = "3003", publishTimeoutMs = "1001", publishPeriodMs = "2002", credentialsPath = CREDENTIALS_FILE_SECOND_PATH, - clientId = "id123", - clientSecret = "secret123", buildFormat = BuildFormat.AAB, buildFile = ARTIFACT_AAB_FILE_SECOND_PATH, releaseTime = "2019-10-18T21:00:00+0300", @@ -324,7 +422,6 @@ internal class ConfigProviderTest { } } - @Suppress("LongMethod") @Test fun `correct config with overriding release notes`() { val expectedConfig = HuaweiPublishConfig( diff --git a/sample-groovy/build.gradle b/sample-groovy/build.gradle index c96045a..26f7541 100644 --- a/sample-groovy/build.gradle +++ b/sample-groovy/build.gradle @@ -21,6 +21,7 @@ huaweiPublish { buildFormat = "apk" } fullRelease { + credentials = "ewogICJjbGllbnRfaWQiOiAiPENMSUVOVF9JRF9CQVNFNjQ+IiwKICAiY2xpZW50X3NlY3JldCI6ICI8Q0xJRU5UX1NFQ1JFVF9CQVNFNjQ+Igp9" credentialsPath = "$projectDir/huawei-credentials-2.json" deployType = "publish" buildFormat = "aab" diff --git a/sample-kotlin/build.gradle.kts b/sample-kotlin/build.gradle.kts index 48459df..72eeb6c 100644 --- a/sample-kotlin/build.gradle.kts +++ b/sample-kotlin/build.gradle.kts @@ -7,7 +7,8 @@ plugins { huaweiPublish { instances { create("release") { - credentialsPath = "$projectDir/huawei-credentials.json" + credentials = "ewogICJjbGllbnRfaWQiOiAiPENMSUVOVF9JRF9CQVNFNjQ+IiwKICAiY2xpZW50X3NlY3JldCI6ICI8Q0xJRU5UX1NFQ1JFVF9CQVNFNjQ+Igp9" +// credentialsPath = "$projectDir/huawei-credentials.json" deployType = ru.cian.huawei.publish.DeployType.DRAFT buildFormat = ru.cian.huawei.publish.BuildFormat.AAB publishSocketTimeoutInSeconds = 60 From 7cd7a955ed5cd348704b186c502d675bb24bfc6e Mon Sep 17 00:00:00 2001 From: Aleksandr Mirko Date: Thu, 17 Oct 2024 14:53:05 +0100 Subject: [PATCH 9/9] Release v1.5.0 --- CHANGELOG.md | 5 +++-- README.md | 2 +- gradle/libs.versions.toml | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 ++-- plugin/gradle.properties | 4 ++-- sample-groovy/build.gradle | 2 +- settings.gradle.kts | 2 +- 7 files changed, 11 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 89ef98f..007b57c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# 1.4.3 +# 1.5.0 ##### Add * [issue#58] Add new `publishSocketTimeoutInSeconds` parameter to change the socket timeout for publish requests in seconds. @@ -14,7 +14,8 @@ } } ``` -* Remove support of `clientId` and `clientSecret` CLI params. Use `credentials` param instead. +* Change classpath dependency from `ru.cian:huawei-publish-gradle-plugin:` to `ru.cian.huawei-plugin:plugin:`. +* Remove support of `clientId` and `clientSecret` CLI params. Use `credentials` or `credentialsPath` params instead. # 1.4.2 diff --git a/README.md b/README.md index 0e8cc31..840e94a 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ buildscript { } dependencies { - classpath "ru.cian:huawei-publish-gradle-plugin:" + classpath "ru.cian.huawei-plugin:plugin:" } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bc13419..5925359 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,7 @@ kotlin = "1.9.22" detekt = "1.23.4" junitJupiter = "5.9.3" androidGradlePlugin = "8.6.0" -sampleHuaweiPlugin = "1.4.3-alpha02" +sampleHuaweiPlugin = "1.5.0" [libraries] appcompat = "androidx.appcompat:appcompat:1.6.1" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2177217..cced4b3 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sun Dec 27 15:37:46 CET 2020 +#Mon Oct 07 08:14:46 WEST 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-all.zip diff --git a/plugin/gradle.properties b/plugin/gradle.properties index 0fb9fba..706f94a 100644 --- a/plugin/gradle.properties +++ b/plugin/gradle.properties @@ -8,8 +8,8 @@ android.enableJetifier=true #################################################################################################### -GROUP=ru.cian -VERSION_NAME=1.4.3-alpha02 +GROUP=ru.cian.huawei-plugin +VERSION_NAME=1.5.0 REQUIRED_JDK_VERSION=17 diff --git a/sample-groovy/build.gradle b/sample-groovy/build.gradle index 26f7541..b9db997 100644 --- a/sample-groovy/build.gradle +++ b/sample-groovy/build.gradle @@ -6,7 +6,7 @@ buildscript { dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:" + libs.versions.kotlin.get() - classpath "ru.cian:plugin:" + libs.versions.sampleHuaweiPlugin.get() + classpath "ru.cian.huawei-plugin:plugin:" + libs.versions.sampleHuaweiPlugin.get() } } diff --git a/settings.gradle.kts b/settings.gradle.kts index 637343d..ec600b4 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -17,7 +17,7 @@ pluginManagement { resolutionStrategy { eachPlugin { if(requested.id.namespace == "ru.cian") { - useModule("ru.cian:plugin:${samplePublishVersion}") + useModule("ru.cian.huawei-plugin:plugin:${samplePublishVersion}") } } }