Skip to content

Commit 3ada93c

Browse files
authored
[infra] support local dev-channel uploads (#8949)
Adds support for local `dev` channel builds and deployments to the JetBrains Marketplace for `flutter-intellij`, comparable to what we did for the Dart plugin: flutter/dart-intellij-third-party#340. Along the way we found some gradle issues and curl failures and added safeguards for Gradle Configuration Cache invalidation and more verbose local diagnostics. Fixes: #8925 --- ### Key Changes #### 1. Gradle Build & Versioning (`build.gradle.kts`) - **Dynamic Git Hash Fallback**: Dynamically resolves the Git commit hash prefix (`git rev-parse --short HEAD`) as part of the `dev` channel version calculation if the `KOKORO_GIT_COMMIT` environment variable is absent. - **Configuration-Cache Safety**: Refactored the `dev`, `release`, and `singleIdeVersion` project property lookups to use the modern Gradle `providers.gradleProperty(...)` API. This registers properties as configuration inputs, ensuring correct cache invalidation when switching project parameters. - **Dynamic Version Inspection**: Registered a new, configuration-cache safe `printVersion` task to easily query the calculated plugin version from the command line. - **Robust Catching**: Handled potential compilation/CLI environment crashes gracefully (e.g., if git is not present or executing outside of a git clone) with comprehensive code comments. #### 2. Kokoro Deployment Pipeline (`tool/kokoro/deploy.sh`) - **Token Injection**: Added support for the `JB_MARKETPLACE_TOKEN` environment variable to allow local authorization token injection. - **Visible Debugging**: Removed the `--fail` option and replaced it with `curl -i` to ensure full JetBrains Marketplace error payloads are printed directly to standard output on error rather than hidden behind generic curl exit codes. - **Robust Zip Path Matching**: Fallback to `flutter-intellij.zip` automatically if not running inside the Kokoro pipeline directory structure. - **Local Setup Quality-of-Life**: Updated `setup.sh` to bypass cloning the Flutter SDK if `../flutter` is already present locally, making local pipeline test runs pain-free. --- ### Verification & Testing #### 1. Version calculation matches local Git state: ```bash $ ./gradlew printVersion -Pdev flutterPluginVersion: 93.0.0-dev.20260506-9a1a847 ... > Task :printVersion 93.0.0-dev.20260506-9a1a847 ``` **Verified deployment** 👍 : <img width="2314" height="772" alt="image" src="https://github.com/user-attachments/assets/0059bb70-31a7-4401-bcd1-20077f56431b" /> --- Review the contribution guidelines below: - [x] I’ve reviewed the contributor guide and applied the relevant portions to this PR. - [x] I've included the required information in the description above. - [x] My up-to-date information is in the `AUTHORS` file. - [x] I've updated `CHANGELOG.md` if appropriate. <details> <summary>Contribution guidelines:</summary><br> - See our [contributor guide](../CONTRIBUTING.md) and the [Flutter organization contributor guide]([https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md) for general expectations for PRs. - Larger or significant changes should be discussed in an issue before creating a PR. - Dart contributions to our repos should follow the [Dart style guide](https://dart.dev/guides/language/effective-dart) and use `dart format`. - Java and Kotlin contributions should strive to follow Java and Kotlin best practices ([discussion](#8098)). </details>
1 parent 3ab1d89 commit 3ada93c

2 files changed

Lines changed: 57 additions & 14 deletions

File tree

build.gradle.kts

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget
1515
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
1616
import java.time.LocalDate
1717
import java.time.format.DateTimeFormatter
18+
import org.gradle.api.DefaultTask
19+
import org.gradle.api.provider.Property
20+
import org.gradle.api.tasks.Input
21+
import org.gradle.api.tasks.TaskAction
1822

1923
// Specify UTF-8 for all compilations so we avoid Windows-1252.
2024
allprojects {
@@ -50,21 +54,34 @@ plugins {
5054
// By default (e.g. when we call `runIde` during development), the plugin version is SNAPSHOT
5155
var flutterPluginVersion = "SNAPSHOT"
5256

57+
val isRelease = providers.gradleProperty("release").isPresent
58+
val isDev = providers.gradleProperty("dev").isPresent
59+
val singleIdeVersionProvider = providers.gradleProperty("singleIdeVersion")
60+
5361
// Otherwise, we will decide on the proper semver-formatted version from the CHANGELOG.
5462
// Note: The CHANGELOG follows the style from https://keepachangelog.com/en/1.0.0/ so that we can use the gradle changelog plugin.
55-
if (project.hasProperty("release")) {
63+
if (isRelease) {
5664
// If we are building for a release, the changelog should be updated with the latest version.
5765
flutterPluginVersion = changelog.getLatest().version
58-
} else if (project.hasProperty("dev")) {
66+
} else if (isDev) {
5967
// If we are building the dev version, the version label will increment the latest version from the changelog and append the date.
6068
val latestVersion = changelog.getLatest().version
6169
val majorVersion = latestVersion.substringBefore('.').toInt()
6270
val nextMajorVersion = majorVersion + 1
6371
val datestamp = DateTimeFormatter.ofPattern("yyyyMMdd").format(LocalDate.now())
6472
flutterPluginVersion = "$nextMajorVersion.0.0-dev.$datestamp"
6573

66-
val commitHash = System.getenv("KOKORO_GIT_COMMIT")
67-
if (commitHash is String) {
74+
val commitHash = System.getenv("KOKORO_GIT_COMMIT") ?: try {
75+
providers.exec {
76+
commandLine("git", "rev-parse", "--short", "HEAD")
77+
}.standardOutput.asText.get().trim()
78+
} catch (e: Exception) {
79+
// Catching all exceptions here is intentional: if git is not installed, or if this is built
80+
// outside of a git repository clone (e.g. from a source zip release), we want the build
81+
// to gracefully proceed with an empty hash instead of crashing.
82+
""
83+
}
84+
if (commitHash.isNotEmpty()) {
6885
val shortCommitHash = commitHash.take(7)
6986
flutterPluginVersion += "-$shortCommitHash"
7087
}
@@ -305,8 +322,8 @@ intellijPlatform {
305322

306323
ides {
307324
// `singleIdeVersion` is only intended for use by GitHub actions to enable deleting instances of IDEs after testing.
308-
if (project.hasProperty("singleIdeVersion")) {
309-
val singleIdeVersion = project.property("singleIdeVersion") as String
325+
if (singleIdeVersionProvider.isPresent) {
326+
val singleIdeVersion = singleIdeVersionProvider.get()
310327
select {
311328
types = listOf(IntelliJPlatformType.AndroidStudio)
312329
channels = listOf(ProductRelease.Channel.RELEASE)
@@ -322,7 +339,7 @@ intellijPlatform {
322339

323340
// If we don't delete old versions of the IDE during `verifyPlugin`, then GitHub action bots can run out of space.
324341
tasks.withType<VerifyPluginTask> {
325-
if (project.hasProperty("singleIdeVersion")) {
342+
if (singleIdeVersionProvider.isPresent) {
326343
doLast {
327344
ides.forEach { ide ->
328345
if (ide.exists()) {
@@ -523,3 +540,17 @@ tasks.withType<ProcessResources>().configureEach {
523540
exclude("jxbrowser/jxbrowser.properties")
524541
}
525542
}
543+
544+
abstract class PrintVersionTask : DefaultTask() {
545+
@get:Input
546+
abstract val pluginVersion: Property<String>
547+
548+
@TaskAction
549+
fun action() {
550+
println(pluginVersion.get())
551+
}
552+
}
553+
554+
tasks.register<PrintVersionTask>("printVersion") {
555+
pluginVersion.set(intellijPlatform.pluginConfiguration.version)
556+
}

tool/kokoro/deploy.sh

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,43 @@
11
#!/bin/bash
22

3+
# To run this script locally from the repository root:
4+
# JB_MARKETPLACE_TOKEN="your_real_token" ./tool/kokoro/deploy.sh
5+
36
source ./tool/kokoro/setup.sh
47
setup
58

69
echo "kokoro build start"
710

8-
./gradlew buildPlugin -Pdev
11+
./gradlew buildPlugin -Pdev --no-configuration-cache
912

1013
echo "kokoro build finished"
1114

1215
echo "kokoro deploy start"
1316

14-
KOKORO_TOKEN_FILE="${KOKORO_KEYSTORE_DIR}/${FLUTTER_KEYSTORE_ID}_${FLUTTER_KEYSTORE_NAME}"
15-
if [ ! -f "$KOKORO_TOKEN_FILE" ]; then
16-
echo "Error: Keystore token file not found at $KOKORO_TOKEN_FILE"
17-
exit 1
17+
if [ -n "$JB_MARKETPLACE_TOKEN" ]; then
18+
TOKEN="$JB_MARKETPLACE_TOKEN"
19+
echo "Using token from JB_MARKETPLACE_TOKEN environment variable."
20+
else
21+
KOKORO_TOKEN_FILE="${KOKORO_KEYSTORE_DIR}/${FLUTTER_KEYSTORE_ID}_${FLUTTER_KEYSTORE_NAME}"
22+
if [ ! -f "$KOKORO_TOKEN_FILE" ]; then
23+
echo "Error: Keystore token file not found at $KOKORO_TOKEN_FILE"
24+
echo "Please set JB_MARKETPLACE_TOKEN or ensure KOKORO_KEYSTORE_DIR is set correctly."
25+
exit 1
26+
fi
27+
TOKEN=$(cat "$KOKORO_TOKEN_FILE")
1828
fi
19-
TOKEN=$(cat "$KOKORO_TOKEN_FILE")
2029

2130
ZIP_FILE="build/distributions/flutter-intellij-kokoro.zip"
31+
if [ ! -f "$ZIP_FILE" ]; then
32+
ZIP_FILE="build/distributions/flutter-intellij.zip"
33+
fi
2234
if [ ! -f "$ZIP_FILE" ]; then
2335
echo "Error: Zip file not found at $ZIP_FILE"
2436
exit 1
2537
fi
2638

2739
echo "Uploading $ZIP_FILE to JetBrains Marketplace..."
28-
curl -if --fail \
40+
curl -if \
2941
--header "Authorization: Bearer $TOKEN" \
3042
-F pluginId=9212 \
3143
-F file=@"$ZIP_FILE" \

0 commit comments

Comments
 (0)