Skip to content

Migrate to AGP's androidComponents/Artifacts API and support AGP 9.x#283

Open
tnj wants to merge 13 commits into
feat/support-configuration-cachefrom
feat/support-agp-9x
Open

Migrate to AGP's androidComponents/Artifacts API and support AGP 9.x#283
tnj wants to merge 13 commits into
feat/support-configuration-cachefrom
feat/support-agp-9x

Conversation

@tnj

@tnj tnj commented Jun 3, 2026

Copy link
Copy Markdown
Member

Summary

Adds support for the current Android Gradle Plugin (9.x) by migrating the plugin off the deprecated/removed Variant API and the reflection into AGP's internal package tasks, onto the public androidComponents + Artifacts API — exactly as AGP's official migration guidance instructs. This removes all AGP-version-specific branching and was validated end-to-end (real APK/AAB build + upload) against AGP 9.2.0 / Gradle 9.4.1 and AGP 8.13.0 / Gradle 8.13 locally via the DeployGate mock server.

The minimum supported AGP is raised to 7.0 (Gradle 7.0+); AGP 4.2.x–6.x are no longer compatible because they predate androidComponents.

What changed

Core migration

  • Iterate variants via androidComponents.onVariants(...) instead of project.android.applicationVariants. Accessed dynamically (getByName + org.gradle.api.Action) because the plugin runs on a classloader separate from AGP — a typed reference throws ClassNotFoundException at runtime.
  • New artifacts/VariantArtifacts: resolves the final APK/AAB through variant.artifacts.get(SingleArtifact.APK/BUNDLE) + BuiltArtifactsLoader, looking up the artifact constants via the variant's classloader (getClass().classLoader).
  • Deleted PackageAppTaskCompat, IApplicationVariant(Impl), and the AGP version gates (isInternalSigningConfigData / hasOutputsHandlerApiOnPackageApplication) — no longer needed with the stable public API.
  • skipAssemble deployments read from AGP's conventional output directory (build/outputs/apk/<flavorName>/<buildType>, build/outputs/bundle/<variant>) so a separately-built artifact can still be uploaded without depending on (or triggering) the build. The strict Artifacts API provider cannot be queried before its producing task runs, so this path intentionally avoids it.
  • Signing readiness is no longer pre-checked (the new SigningConfig exposes no such getter); DeployGate rejects unsigned uploads server-side.

Gradle 9 build/test compatibility

  • java {} extension for source/target compatibility; Spock groovy-4.0 on Gradle 9; JUnit Platform launcher on the test runtime; --add-opens for ProjectBuilder; guarded the pre-7.5 ModuleRegistry workaround and the pre-7.1 GradlePropertiesController test workaround.

Tests & fixtures

  • ConfigurationCacheSpec moved into the acceptance source set and parameterized by TEST_AGP_VERSION/TEST_GRADLE_VERSION (it previously hardcoded AGP 4.2.0).
  • Acceptance fixtures: only compileSdkVersioncompileSdk (property) is required for AGP 9 (the method was removed); set to 30, which is AGP 7.0.0's maximum and AGP 9.x's minimum compileSdk. The flavor DSL keeps the vararg method form (flavorDimensions "a","b", dimension "x") because AGP 7.0.0 exposes flavorDimensions as a read-only property (so += [...] fails there), while the method forms still work on AGP 9.2. Also: proguard-android-optimize.txt (AGP 9 rejects proguard-android.txt) and android:exported on the launcher activity.

CI & docs

  • Drop the AGP 4.2.0 rows; add AGP 9.0.0/9.1.0/9.2.0 with their minimum Gradle (9.1.0 / 9.3.1 / 9.4.1) on JDK 17.
  • README/README_JP: 2.10.0 requires AGP 7.0+/Gradle 7.0+; AGP 9.x documented as supported.

Verification

The full CI matrix is green — acceptance-test-runtime-env passes for all 22 AGP versions (7.0.0 → 9.2.0), plus lint, unit, and unroll-acceptance jobs.

Additionally run locally against the DeployGate mock server (real build + upload):

Check Result
testPluginAcceptanceTest (full) ✅ AGP 7.0.0/Gradle 7.0.2, 8.0.0/Gradle 8.0, 8.13.0/Gradle 8.13, 9.2.0/Gradle 9.4.1
ConfigurationCacheSpec ✅ AGP 9.2.0/Gradle 9.4.1
unit :test ✅ Gradle 9.4.1 and wrapper 6.7.1

Changelog (targeting 2.10.0)

Proposed CHANGELOG entry for this PR (to be combined with the configuration-cache work in #272):

  • Support the current Android Gradle Plugin line:
    • 8.8.x – 8.13.x
    • 9.0.x with Gradle 9.1.0
    • 9.1.x with Gradle 9.3.1
    • 9.2.x with Gradle 9.4.1
  • Migrate variant/artifact handling to AGP's public androidComponents + Artifacts API (no reflection into internal AGP tasks), preserving configuration-cache compatibility.
  • skipAssemble deployments without an explicit sourceFile now resolve the artifact from AGP's conventional output directory (build/outputs/apk/<flavor>/<buildType>, build/outputs/bundle/<variant>) instead of reading the package task's configured output location. Behavior is unchanged for standard projects; projects that relocate the APK/AAB output should set sourceFile explicitly.

Breaking Changes

  • Drop support for Android Gradle Plugin 4.2.x–6.x. The minimum supported AGP is now 7.0 and the minimum Gradle is now 7.0 (the plugin relies on AGP's androidComponents/Artifacts API, which does not exist before AGP 7.0).
  • AGP 9.x additionally requires JDK 17 (an AGP requirement).
  • Removed the client-side unsigned-APK pre-check. The plugin no longer fails early with "Cannot upload a build without code signature to DeployGate"; unsigned uploads are now rejected by the DeployGate server instead, because the new Variant API exposes no way to detect signing readiness at configuration time.

Notes for review

  • Base is feat/support-configuration-cache (not yet merged), so this PR shows only the AGP 9.x migration on top of it.
  • Minimum AGP raised to 7.0 / Gradle 7.0 is a deliberate, documented breaking change for 2.10.0.

🤖 Generated with Claude Code

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the Gradle DeployGate Plugin to support AGP 9.x and Gradle 9.x by migrating from internal AGP APIs to the public androidComponents and Artifacts API. It also updates test suites, build configurations, and dependencies to align with Gradle 9 requirements. The review feedback highlights a syntax issue in build.gradle where a trailing comma in jvmArgs could break compatibility with older Gradle versions running Groovy 2.5. Additionally, improvements are suggested in VariantArtifacts.groovy to ensure robust file matching for .aab artifacts and to use .getClass() instead of .class to prevent dynamic property resolution issues in Groovy.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread build.gradle
Comment thread src/main/groovy/com/deploygate/gradle/plugins/artifacts/VariantArtifacts.groovy Outdated
Comment thread src/main/groovy/com/deploygate/gradle/plugins/artifacts/VariantArtifacts.groovy Outdated

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Open in Devin Review

@tnj tnj force-pushed the feat/support-agp-9x branch from 329c6c4 to 833d83a Compare June 3, 2026 04:56
@tnj tnj requested a review from Copilot June 3, 2026 05:45

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR migrates the plugin’s Android Gradle Plugin integration to the public androidComponents + Artifacts API in order to support AGP 9.x, while updating tests/fixtures, CI matrix, and documentation to reflect the new minimum supported AGP/Gradle versions.

Changes:

  • Replace deprecated Variant API/internal task reflection with androidComponents.onVariants + SingleArtifact resolution (new VariantArtifacts helper).
  • Modernize acceptance/unit test fixtures for AGP 7.0+ / Gradle 9 compatibility (DSL updates, exported activity, configuration-cache spec parameterization).
  • Update build logic, CI matrix, and README/README_JP to document and exercise AGP 9.x support and the new minimum versions.

Reviewed changes

Copilot reviewed 15 out of 16 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/test/resources/project/src/main/AndroidManifest.xml Adds android:exported to keep the fixture compatible with newer Android tooling expectations.
src/test/resources/project/build.gradle Updates fixture DSL to AGP 7+ style and adjusts SDK/proguard defaults.
src/test/resources/acceptance/android_block.gradle Updates acceptance fixture compile/target/proguard defaults for newer AGP.
src/test/groovy/com/deploygate/gradle/plugins/internal/agp/AndroidGradlePluginSpec.groovy Removes unit tests tied to deleted AGP-version-gating helpers.
src/test/groovy/com/deploygate/gradle/plugins/DeployGatePluginSpec.groovy Makes the Gradle <7.1 ProjectBuilder workaround conditional and reflection-based for Gradle 9 compatibility.
src/test/acceptance/com/deploygate/gradle/plugins/ConfigurationCacheSpec.groovy Parameterizes AGP/Gradle versions and refactors configuration-cache acceptance coverage.
src/main/groovy/com/deploygate/gradle/plugins/internal/agp/IApplicationVariantImpl.groovy Removes old Variant API proxy implementation.
src/main/groovy/com/deploygate/gradle/plugins/internal/agp/IApplicationVariant.groovy Removes old Variant API proxy interface.
src/main/groovy/com/deploygate/gradle/plugins/internal/agp/AndroidGradlePlugin.groovy Deletes AGP-version-gate helpers no longer needed with the public Artifacts API.
src/main/groovy/com/deploygate/gradle/plugins/DeployGatePlugin.groovy Switches variant iteration to androidComponents.onVariants and wires upload tasks via VariantArtifacts.
src/main/groovy/com/deploygate/gradle/plugins/artifacts/VariantArtifacts.groovy Introduces new artifact resolution implementation for APK/AAB (Artifacts API + conventional outputs for skipAssemble).
src/main/groovy/com/deploygate/gradle/plugins/artifacts/PackageAppTaskCompat.groovy Removes legacy reflection-based package task compatibility layer.
README.md Documents AGP 9.x support and the new minimum supported AGP/Gradle versions.
README_JP.md Same as README.md, in Japanese.
build.gradle Updates build/test dependencies and JVM args for Gradle 9 / Groovy 4 / JUnit Platform launcher behavior.
.github/workflows/build-and-test.yml Updates the CI matrix to drop AGP 4.2 and add AGP 9.0–9.2 with appropriate Gradle/JDK versions.
Comments suppressed due to low confidence (2)

src/test/acceptance/com/deploygate/gradle/plugins/ConfigurationCacheSpec.groovy:116

  • GradleRunner.withGradleVersion(...) is called with TEST_GRADLE_VERSION directly. If that env var is unset (e.g., when running the spec locally), withGradleVersion(null) will fail. Provide a safe fallback to the current Gradle version so the spec can run without requiring env setup.
    src/test/acceptance/com/deploygate/gradle/plugins/ConfigurationCacheSpec.groovy:277
  • configurationCacheRunner also calls withGradleVersion(System.getenv("TEST_GRADLE_VERSION")) without a null-safe fallback, which can break local runs when the env var isn’t set.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@tnj tnj requested a review from satsukies June 3, 2026 06:14
tnj and others added 12 commits June 5, 2026 17:24
Gradle 9 removed/changed several build-script and test-runtime behaviors. Apply
the minimal, backward-compatible fixes so the build configures, compiles, and
runs unit tests on both Gradle 6.7.1 (current wrapper) and Gradle 9.4.1:

- Move sourceCompatibility/targetCompatibility into the `java {}` extension
  (the project-level convention was removed in Gradle 9).
- Select the Spock `groovy-4.0` variant when running on Gradle 9.0+ (which
  bundles Groovy 4); keep groovy-3.0 / groovy-2.5 for older Gradle.
- Add the JUnit Platform launcher to the test runtime (Gradle 9 no longer
  provides it automatically).
- Add `--add-opens` JVM args to Test tasks so ProjectBuilder can inject
  synthetic classes under the JDK module system.
- Guard the gradle-tooling-api-builders workaround to Gradle < 7.5; the
  internal ModuleRegistry#classpath it relies on was removed in Gradle 9.
- In DeployGatePluginSpec, call the pre-7.1 GradlePropertiesController
  workaround reflectively and only on Gradle < 7.1 (the type moved in Gradle 9).

Verified: unit tests green on Gradle 6.7.1 (155/155). On Gradle 9.4.1 only
ConfigurationCacheSpec fails because it hardcodes AGP 4.2.0; that is addressed
by the Variant API migration.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…cts API

Replace the deprecated/removed AGP Variant API and the reflection into internal
package tasks with the public androidComponents API, per AGP's official guidance.
This is the core of AGP 9.x support and removes all AGP-version-specific branching.

- DeployGatePlugin: iterate variants via androidComponents.onVariants(...) instead
  of project.android.applicationVariants. Accessed dynamically (getByName + Action)
  because the plugin runs on a classloader separate from AGP; a typed reference
  throws ClassNotFoundException at runtime.
- New artifacts/VariantArtifacts: resolves the final APK/AAB via
  variant.artifacts.get(SingleArtifact.APK/BUNDLE) + BuiltArtifactsLoader, looking
  up the artifact constants through the variant's classloader.
- Delete PackageAppTaskCompat, IApplicationVariant(Impl), and the AGP version
  gates (isInternalSigningConfigData / hasOutputsHandlerApiOnPackageApplication)
  with their spec. Signing readiness is no longer pre-checked (server rejects
  unsigned uploads), per product decision.

This raises the effective minimum to AGP 7.0 (androidComponents/Artifacts API).

Verified locally (mock server): 12/14 AcceptanceTestSpec pass on AGP 8.13/Gradle
8.13 (all happy paths, customApk, negative cases). Known remaining work:
- skipAssemble + pre-built artifact: the strict Artifacts API provider cannot be
  queried before its producing task completes; needs a dependency-free read path
  (2 acceptance cases).
- ConfigurationCacheSpec hardcodes AGP 4.2.0 (incompatible with the new API);
  must be parameterized to AGP 7.0+/new DSL, along with the shared acceptance
  fixture, the version floor, CI matrix, and README (Step 3).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The strict Artifacts API provider cannot be queried unless its producing task
runs in the same build, which conflicts with skipAssemble deployments (upload a
separately-built artifact without depending on assemble/bundle).

For skipAssemble, read the artifact from AGP's conventional output directory
(build/outputs/apk/<flavorName>/<buildType>, build/outputs/bundle/<variant>)
using the variant's flavorName/buildType and BuiltArtifactsLoader — no dependency
on, and no triggering of, the build. The assembled path keeps using the strict
provider plus a dependsOn the assemble/bundle task.

All 14 AcceptanceTestSpec cases pass on AGP 8.13/Gradle 8.13 (mock server),
including the skipAssemble "require assembling/bundling" cases.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Update the shared acceptance fixture so it builds on AGP 9.x while remaining
compatible with AGP 7.0+ (the new minimum):

- Use the new DSL property assignment form: compileSdk/minSdk/targetSdk,
  flavorDimensions += [...], dimension =, applicationIdSuffix = (the legacy
  compileSdkVersion(int)/dimension(...) methods were removed in AGP 9.0).
- Raise compileSdk/targetSdk to 36 and minSdk to 21; drop the pinned
  buildToolsVersion (AGP defaults to 36.0.0).
- Use proguard-android-optimize.txt; proguard-android.txt is rejected in AGP 9
  because it implies -dontoptimize.
- Declare android:exported on MainActivity (required since Android 12 / targetSdk 31+).

Verified: all 14 AcceptanceTestSpec cases pass on both AGP 9.2.0/Gradle 9.4.1
and AGP 8.13.0/Gradle 8.13 via the mock server (real APK/AAB build + upload).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ConfigurationCacheSpec hardcoded AGP 4.2.0 and ran on the ambient Gradle, which
is incompatible with the new androidComponents/Artifacts API (AGP 7.0+). Move it
into the pluginAcceptanceTest source set so it runs across the AGP/Gradle/JDK
matrix, drive the AGP classpath from TEST_AGP_VERSION, pin the inner build to
TEST_GRADLE_VERSION via withGradleVersion, and switch the inline projects to the
new DSL (extracted into an androidProject() helper). Also migrate the shared
project/build.gradle fixture (used by AndroidGradlePluginAcceptanceSpec) to the
new DSL + proguard-android-optimize.txt.

Verified on the mock server: full testPluginAcceptanceTest green on AGP 9.2.0/
Gradle 9.4.1 and AGP 8.13.0/Gradle 8.13; unit :test green on Gradle 9.4.1.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The androidComponents/Artifacts API migration raises the minimum to AGP 7.0, so
remove the AGP 4.2.0 rows and add AGP 9.0.0/9.1.0/9.2.0 with their minimum Gradle
versions (9.1.0 / 9.3.1 / 9.4.1) on JDK 17.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…pport

Reflect the androidComponents/Artifacts API migration: 2.10.0 raises the minimum
to AGP 7.0 and Gradle 7.0, and AGP 9.0/9.1/9.2 are now verified in CI. Cap AGP
4.2.x at <2.10.0 and add the 9.x compatibility rows.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
compileSdk 36 (introduced when modernizing the fixtures) is rejected by
AGP 7.0–8.0 — the runtime-env CI matrix failed for those versions. AGP 9.x in
turn requires compileSdk >= 30 ("In order to compile Java 9+ source"). Use
compileSdk/targetSdk 31, which AGP 7.0 supports (its max) and AGP 9.2 accepts.

Verified locally via the mock server: full testPluginAcceptanceTest passes on
AGP 8.0.0/Gradle 8.0 (previously failing) and AGP 9.2.0/Gradle 9.4.1.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Match the AAB only against files (`it.isFile() && ...`), not a directory that
  happens to end with `.aab`.
- Use `variant.getClass()` instead of `variant.class` so dynamic property
  interception on decorated AGP domain objects cannot shadow the lookup.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CI showed AGP 7.0.0 still failing with compileSdk 31 — AGP 7.0.0 only supports
up to compileSdk 30. AGP 9.x requires compileSdk >= 30, so 30 is the single
value compatible across the whole AGP 7.0–9.2 matrix. Verified locally (mock
server) that full testPluginAcceptanceTest passes on AGP 8.0.0/Gradle 8.0 and
AGP 9.2.0/Gradle 9.4.1 with android-30 installed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
….0.0

AGP 7.0.0 exposes `flavorDimensions` as a read-only property, so
`flavorDimensions += [...]` fails ("Cannot set the value of read-only property").
The vararg method forms (`flavorDimensions "a","b"`, `dimension "x"`,
`applicationIdSuffix`, `minSdkVersion`/`targetSdkVersion`, `minifyEnabled`) still
work on AGP 9.2, so use them — only `compileSdk` needs the property form
(`compileSdkVersion` is removed in AGP 9). compileSdk stays at 30 (AGP 7.0.0's max,
and AGP 9.x's minimum).

Verified locally (mock server): full testPluginAcceptanceTest passes on
AGP 7.0.0/Gradle 7.0.2 and AGP 9.2.0/Gradle 9.4.1.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…lution

- Guard `artifactFileProvider` against a null `artifactFilePath` so an unbuilt
  skipAssemble deployment (no sourceFile) yields the existing "artifact not found"
  error instead of an NPE from `new File(null)`.
- Resolve `BuiltArtifact.outputFile` against the APK artifact directory when it is
  relative (it is absolute on supported AGP versions, but resolve defensively).

Verified on AGP 9.2.0/Gradle 9.4.1: full AcceptanceTestSpec happy paths, the
skipAssemble "should fail" / "require assembling" cases, and unit :test all pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@tnj tnj force-pushed the feat/support-agp-9x branch from e9b9646 to 8249b8b Compare June 5, 2026 08:42

@satsukies satsukies left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work, thank you!
I added some comments and a question, please check them.

"""

when: "Running the task with configuration cache enabled"
def gradleVersion = System.getenv("TEST_GRADLE_VERSION")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nits]
At line 54, the value "8.7.0" is set as a fallback if System.getenv() returns null.
Would you also consider to handle null at here? (e.g., set fallback value, etc)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. I'll add Gradle version fallbacks.

def elements = builtArtifacts?.elements ?: []
File apkFile = elements.isEmpty() ? null : resolveOutputFile(apkDirectory, elements.iterator().next().outputFile)
// DeployGate only accepts a single universal APK; multiple elements imply split APKs.
boolean universal = elements.size() == 1

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[ask]
loader.load() method read the metadata from buildDir.
elements.size() equals zero before build a project: no artifact exists in buildDir.
So it may be misunderstand as a split apk.
Is this behavior what you expect?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, 0 shouldn't mean a split apk. I'll fix it, too

boolean universal = elements.size() == 1
// Signing readiness is no longer pre-checked here: the public API does not expose it,
// and DeployGate rejects unsigned uploads server-side.
return new DirectApkInfo(variantName, apkFile, true, universal)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[note]
3rd argument isSigningReady is always true, it becomes meaningless.
In the future, we can maybe consider refactoring this code.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remove them. I thought we'll restore it if we find a way to retrieve that status again in the future, but we ain't gonna need it.

… dead isSigningReady

- ConfigurationCacheSpec: fall back to Gradle 8.9 when TEST_GRADLE_VERSION
  is unset so the spec runs locally without env setup.
- VariantArtifacts: treat an empty Artifacts result (APK not built yet) as
  non-split so the null artifact surfaces the clear "artifact was not found"
  error instead of a misleading "non-universal apk" one.
- Remove the now-meaningless isSigningReady flag end to end: the public
  Artifacts API does not expose signing state and DeployGate rejects unsigned
  uploads server-side, so the local check was always-true dead code.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@satsukies satsukies left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your great work!
LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants