Muzzle CI experiment (#5594)
* Muzzle CI experiment * Fix class loader leak * --max-workers=4 * Concurrent jobs * Update .github/workflows/muzzle.yml Co-authored-by: Anuraag Agrawal <anuraaga@gmail.com> * Simpler * Add link to comment Co-authored-by: Anuraag Agrawal <anuraaga@gmail.com>
This commit is contained in:
parent
ab587a927a
commit
25856b8531
|
@ -2,36 +2,21 @@ name: Muzzle
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_call:
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
cache-read-only:
|
||||||
|
type: boolean
|
||||||
|
required: false
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
setup-matrix:
|
muzzle:
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Set up JDK 11 for running Gradle
|
|
||||||
uses: actions/setup-java@v2
|
|
||||||
with:
|
|
||||||
distribution: temurin
|
|
||||||
java-version: 11
|
|
||||||
|
|
||||||
- name: List instrumentations to file
|
|
||||||
uses: gradle/gradle-build-action@v2
|
|
||||||
with:
|
|
||||||
arguments: instrumentation:listInstrumentations
|
|
||||||
cache-read-only: true
|
|
||||||
|
|
||||||
- id: set-matrix
|
|
||||||
run: echo "::set-output name=matrix::{\"module\":[\"$(cat instrumentation-list.txt | xargs echo | sed 's/ /","/g')\"]}"
|
|
||||||
|
|
||||||
run:
|
|
||||||
needs: setup-matrix
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix: ${{fromJson(needs.setup-matrix.outputs.matrix)}}
|
matrix:
|
||||||
fail-fast: false
|
task:
|
||||||
|
- :instrumentation:muzzle1
|
||||||
|
- :instrumentation:muzzle2
|
||||||
|
- :instrumentation:muzzle3
|
||||||
|
- :instrumentation:muzzle4
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
@ -41,16 +26,8 @@ jobs:
|
||||||
distribution: temurin
|
distribution: temurin
|
||||||
java-version: 11
|
java-version: 11
|
||||||
|
|
||||||
# don't use gradle-build-action because all the parallel muzzle jobs cause the cache service
|
|
||||||
# to respond with 429 (to both muzzle and other jobs running in parallel)
|
|
||||||
|
|
||||||
- name: Run muzzle
|
- name: Run muzzle
|
||||||
# using retry because of sporadic gradle download failures
|
uses: gradle/gradle-build-action@v2
|
||||||
uses: nick-invision/retry@v2.6.0
|
|
||||||
with:
|
with:
|
||||||
# timing out has not been a problem, these jobs typically finish in 2-3 minutes
|
arguments: ${{ matrix.task }}
|
||||||
timeout_minutes: 15
|
cache-read-only: ${{ inputs.cache-read-only }}
|
||||||
# give maven central some time to hopefully recover (120 seconds has not proven to be enough)
|
|
||||||
retry_wait_seconds: 300
|
|
||||||
max_attempts: 5
|
|
||||||
command: ./gradlew ${{ matrix.module }}:muzzle
|
|
||||||
|
|
|
@ -49,6 +49,8 @@ jobs:
|
||||||
# which requires unnecessary release branch maintenance, especially for patches
|
# which requires unnecessary release branch maintenance, especially for patches
|
||||||
if: ${{ !startsWith(github.base_ref, 'v') }}
|
if: ${{ !startsWith(github.base_ref, 'v') }}
|
||||||
uses: ./.github/workflows/muzzle.yml
|
uses: ./.github/workflows/muzzle.yml
|
||||||
|
with:
|
||||||
|
cache-read-only: true
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
uses: ./.github/workflows/examples.yml
|
uses: ./.github/workflows/examples.yml
|
||||||
|
|
|
@ -154,9 +154,8 @@ val hasRelevantTask = gradle.startParameter.taskNames.any {
|
||||||
// removing leading ':' if present
|
// removing leading ':' if present
|
||||||
val taskName = it.removePrefix(":")
|
val taskName = it.removePrefix(":")
|
||||||
val projectPath = project.path.substring(1)
|
val projectPath = project.path.substring(1)
|
||||||
// Either the specific muzzle task in this project or the top level, full-project
|
// Either the specific muzzle task in this project or a top level muzzle task.
|
||||||
// muzzle task.
|
taskName == "${projectPath}:muzzle" || taskName.startsWith("instrumentation:muzzle")
|
||||||
taskName == "${projectPath}:muzzle" || taskName == "muzzle"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasRelevantTask) {
|
if (hasRelevantTask) {
|
||||||
|
|
|
@ -4,6 +4,16 @@ plugins {
|
||||||
|
|
||||||
val instrumentationProjectTest = tasks.named("test")
|
val instrumentationProjectTest = tasks.named("test")
|
||||||
|
|
||||||
|
// batching up the muzzle tasks alphabetically into 4 chunks
|
||||||
|
// to split them up into separate CI jobs (but not too many CI job)
|
||||||
|
val instrumentationProjectMuzzle = listOf(
|
||||||
|
tasks.create("muzzle1"),
|
||||||
|
tasks.create("muzzle2"),
|
||||||
|
tasks.create("muzzle3"),
|
||||||
|
tasks.create("muzzle4")
|
||||||
|
)
|
||||||
|
|
||||||
|
var counter = 0
|
||||||
subprojects {
|
subprojects {
|
||||||
val subProj = this
|
val subProj = this
|
||||||
plugins.withId("java") {
|
plugins.withId("java") {
|
||||||
|
@ -18,19 +28,11 @@ subprojects {
|
||||||
testCompileOnly(project(path = ":testing:armeria-shaded-for-testing", configuration = "shadow"))
|
testCompileOnly(project(path = ":testing:armeria-shaded-for-testing", configuration = "shadow"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
tasks {
|
plugins.withId("io.opentelemetry.instrumentation.muzzle-check") {
|
||||||
register("listInstrumentations") {
|
// relying on predictable ordering of subprojects
|
||||||
group = "Help"
|
// (see https://docs.gradle.org/current/dsl/org.gradle.api.Project.html#N14CB4)
|
||||||
description = "List all available instrumentation modules"
|
// since we are splitting these muzzleX tasks across different github action jobs
|
||||||
doFirst {
|
instrumentationProjectMuzzle[counter++ % 4].dependsOn(subProj.tasks.named("muzzle"))
|
||||||
File("instrumentation-list.txt").printWriter().use { out ->
|
|
||||||
subprojects
|
|
||||||
.filter { it.plugins.hasPlugin("io.opentelemetry.instrumentation.muzzle-check") }
|
|
||||||
.map { it.path }
|
|
||||||
.forEach { out.println(it) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,9 @@ package io.opentelemetry.javaagent.instrumentation.api.internal;
|
||||||
*/
|
*/
|
||||||
public final class InClassLoaderMatcher {
|
public final class InClassLoaderMatcher {
|
||||||
|
|
||||||
private static final ThreadLocal<MutableBoolean> inClassLoaderMatcher =
|
// using boolean[] to avoid an extra thread local lookup for getAndSet() below
|
||||||
ThreadLocal.withInitial(MutableBoolean::new);
|
private static final ThreadLocal<boolean[]> inClassLoaderMatcher =
|
||||||
|
ThreadLocal.withInitial(() -> new boolean[1]);
|
||||||
|
|
||||||
private InClassLoaderMatcher() {}
|
private InClassLoaderMatcher() {}
|
||||||
|
|
||||||
|
@ -24,7 +25,7 @@ public final class InClassLoaderMatcher {
|
||||||
* calls ClassLoader.getResource(). See {@code EclipseOsgiInstrumentationModule} for more details.
|
* calls ClassLoader.getResource(). See {@code EclipseOsgiInstrumentationModule} for more details.
|
||||||
*/
|
*/
|
||||||
public static boolean get() {
|
public static boolean get() {
|
||||||
return inClassLoaderMatcher.get().value;
|
return inClassLoaderMatcher.get()[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,7 +37,10 @@ public final class InClassLoaderMatcher {
|
||||||
* agent class loader.
|
* agent class loader.
|
||||||
*/
|
*/
|
||||||
public static boolean getAndSet(boolean value) {
|
public static boolean getAndSet(boolean value) {
|
||||||
return inClassLoaderMatcher.get().getAndSet(value);
|
boolean[] arr = inClassLoaderMatcher.get();
|
||||||
|
boolean curr = arr[0];
|
||||||
|
arr[0] = value;
|
||||||
|
return curr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,18 +52,6 @@ public final class InClassLoaderMatcher {
|
||||||
* agent class loader.
|
* agent class loader.
|
||||||
*/
|
*/
|
||||||
public static void set(boolean value) {
|
public static void set(boolean value) {
|
||||||
inClassLoaderMatcher.get().value = value;
|
inClassLoaderMatcher.get()[0] = value;
|
||||||
}
|
|
||||||
|
|
||||||
// using MutableBoolean to avoid an extra thread local lookup for getAndSet()
|
|
||||||
private static class MutableBoolean {
|
|
||||||
|
|
||||||
private boolean value;
|
|
||||||
|
|
||||||
private boolean getAndSet(boolean value) {
|
|
||||||
boolean oldValue = this.value;
|
|
||||||
this.value = value;
|
|
||||||
return oldValue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue