Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Build

on:
push:
branches: [ master, "claude/**" ]
pull_request:
branches: [ master ]

concurrency:
group: build-${{ github.ref }}
cancel-in-progress: true

jobs:
build:
name: Build & Verify
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'

- name: Set up Gradle
uses: gradle/actions/setup-gradle@v3
with:
cache-read-only: ${{ github.ref != 'refs/heads/master' }}

- name: Validate Gradle wrapper
uses: gradle/actions/wrapper-validation@v3

- name: Assemble & test
run: ./gradlew assemble check --stacktrace
102 changes: 65 additions & 37 deletions .github/workflows/gradle-publish.yml
Original file line number Diff line number Diff line change
@@ -1,47 +1,75 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow will build a package using Gradle and then publish it to GitHub packages when a release is created
# For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#Publishing-using-gradle
# Publishes the Hunter artifacts to Maven Central via Sonatype Central Portal.
#
# Triggers:
# - manual dispatch (`workflow_dispatch`) for ad-hoc releases / dry-runs
# - tag push of the form `v*` (e.g. `v1.3.0`) for cut releases
#
# Required repository secrets (Settings → Secrets and variables → Actions):
# MAVEN_CENTRAL_USERNAME — Sonatype Central Portal user token name
# MAVEN_CENTRAL_PASSWORD — Sonatype Central Portal user token password
# SIGNING_IN_MEMORY_KEY — ASCII-armored GPG private key (entire block,
# including BEGIN/END lines). Generate with
# `gpg --armor --export-secret-keys <KEY_ID>`.
# SIGNING_IN_MEMORY_KEY_ID — last 8 hex chars of the GPG key (optional)
# SIGNING_IN_MEMORY_KEY_PASSWORD — passphrase for that GPG key
#
# The vanniktech maven-publish plugin reads these via the
# `ORG_GRADLE_PROJECT_*` env-var convention.

name: Gradle Package
name: Publish to Maven Central

on:
workflow_dispatch:
inputs:
dryRun:
description: 'Run :publishToMavenLocal only (skip Central upload)'
required: false
default: 'false'
push:
branches: [ master ]
pull_request:
branches: [ master ]
tags:
- 'v*'

jobs:
build:
concurrency:
group: publish-${{ github.ref }}
cancel-in-progress: false

jobs:
publish:
name: Publish
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read
packages: write

steps:
- uses: actions/checkout@v3
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
settings-path: ${{ github.workspace }} # location for the settings.xml file

- name: Build with Gradle
uses: ./gradlew build --no-daemon
with:
arguments: build

# The USERNAME and TOKEN need to correspond to the credentials environment variables used in
# the publishing section of your build.gradle
- name: Publish to GitHub Packages
uses: ./gradlew build --no-daemon
with:
arguments: publish
env:
USERNAME: ${{ github.actor }}
TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/checkout@v4

- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'

- name: Set up Gradle
uses: gradle/actions/setup-gradle@v3
with:
cache-read-only: false

- name: Validate Gradle wrapper
uses: gradle/actions/wrapper-validation@v3

- name: Verify build before publishing
run: ./gradlew assemble --stacktrace

- name: Publish to Maven Local (dry run)
if: ${{ github.event_name == 'workflow_dispatch' && inputs.dryRun == 'true' }}
run: ./gradlew publishToMavenLocal --stacktrace

- name: Publish to Maven Central
if: ${{ !(github.event_name == 'workflow_dispatch' && inputs.dryRun == 'true') }}
env:
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_CENTRAL_USERNAME }}
ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVEN_CENTRAL_PASSWORD }}
ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.SIGNING_IN_MEMORY_KEY }}
ORG_GRADLE_PROJECT_signingInMemoryKeyId: ${{ secrets.SIGNING_IN_MEMORY_KEY_ID }}
ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.SIGNING_IN_MEMORY_KEY_PASSWORD }}
run: ./gradlew publishAndReleaseToMavenCentral --no-configuration-cache --stacktrace
35 changes: 29 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,47 @@

[中文](https://github.com/Leaking/Hunter/blob/master/docs/README_ch.md)

Hunter is a framework to develop android gradle plugin based on
[ASM](https://asm.ow2.io/) and [Gradle Transform API](http://tools.android.com/tech-docs/new-build-system/transform-api).
Hunter is a framework to develop android gradle plugins based on
[ASM](https://asm.ow2.io/) and the modern AGP
[Instrumentation API](https://developer.android.com/reference/tools/gradle-api/8.7/com/android/build/api/instrumentation/AsmClassVisitorFactory).
It provides a set of useful, scalable plugins for android developers. You can use Hunter to develop more plugins
to monitor your app, enhance 3rd-dependency, enhance android framework. Plugins based on Hunter support incremental and concurrent compile, so you don't need to
be afraid of extra build time.
to monitor your app, enhance 3rd-party deps, or enhance the android framework. Hunter-based plugins inherit
AGP's incremental, parallel instrumentation pipeline, so you don't pay for extra build time.

## Latest Version

Recently, Hunter is published to [MavenCentral](https://repo1.maven.org/maven2/cn/quinnchen/hunter/).

Every libraies / plugins use same latest version, replace LATEST_VERSION_IN_README in others README with this latest version
Every library / plugin uses the same latest version. Replace `LATEST_VERSION_IN_README` in the per-plugin
READMEs with this version.

```groovy

1.2.3
1.3.0

```

## Compatibility

| Hunter | Android Gradle Plugin | Gradle | ASM | Java |
|--------|----------------------------------------------|--------|-----|------|
| 1.3.x | 7.4 – 8.7+ | 8.0+ | 9.7 | 17 |
| 1.2.x | 4.x (legacy Transform API, removed in AGP 8) | 7.x | 7.1 | 8 |

`1.3.0` is a **breaking** release: the legacy `Transform` API is gone (it was
removed by AGP 8.0 — see issues
[#67](https://github.com/Leaking/Hunter/issues/67),
[#63](https://github.com/Leaking/Hunter/issues/63),
[#34](https://github.com/Leaking/Hunter/issues/34)) and Hunter now wires
itself in via `AndroidComponentsExtension.onVariants` +
`AsmClassVisitorFactory`. ASM was bumped to 9.x to support Java 17 records
and sealed classes
([#60](https://github.com/Leaking/Hunter/issues/60),
[#66](https://github.com/Leaking/Hunter/issues/66)). The constructor
instrumentation bug from
[#48](https://github.com/Leaking/Hunter/issues/48) is also fixed: the timing
probe is now injected after the mandatory `super(...)` / `this(...)` call.

## Some useful plugins based on Hunter

+ [OkHttp-Plugin](https://github.com/Leaking/Hunter/blob/master/docs/README_hunter_okhttp.md): Hack Okhttp to set a global Interceptor/Eventlistener/Dns
Expand Down
54 changes: 36 additions & 18 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,31 +1,49 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
// Top-level build file.

allprojects {
buildscript {
repositories {
mavenLocal()
mavenCentral()
google()
}
dependencies {
classpath Libs.AGP
classpath 'com.vanniktech:gradle-maven-publish-plugin:0.17.0'
}
}
buildscript {
repositories {
mavenLocal()
mavenCentral()
google()
mavenCentral()
gradlePluginPortal()
}
dependencies {
classpath Libs.AGP
classpath 'com.vanniktech:gradle-maven-publish-plugin:0.30.0'
}
}

allprojects {
repositories {
mavenLocal()
google()
mavenCentral()
gradlePluginPortal()
}
}

import com.vanniktech.maven.publish.MavenPublishBaseExtension
import com.vanniktech.maven.publish.SonatypeHost

subprojects {
plugins.withId("com.vanniktech.maven.publish") {
mavenPublish {
sonatypeHost = "S01"
extensions.configure(MavenPublishBaseExtension) { ext ->
// Sonatype Central Portal — replaces the deprecated OSSRH that was
// shut down on 2025-06-30.
ext.publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL, true)
// Sign only when a GPG key is configured. Lets ./gradlew
// publishToMavenLocal run on a dev box that has no signing key set
// up, while CI (which exports ORG_GRADLE_PROJECT_signingInMemoryKey)
// still produces signed artifacts for Central.
boolean hasSigningKey = project.findProperty("signingInMemoryKey") != null \
|| System.getenv("ORG_GRADLE_PROJECT_signingInMemoryKey") != null
if (hasSigningKey) {
ext.signAllPublications()
}
}
}
}

task clean(type: Delete) {
delete rootProject.buildDir
tasks.register('clean', Delete) {
delete rootProject.layout.buildDirectory
}
Loading
Loading