Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ci: improve build times for instrumentation image tests #257

Merged
merged 2 commits into from
Feb 2, 2025
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
137 changes: 137 additions & 0 deletions .github/actions/injector-and-instrumentation-tests/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
name: injector and instrumentation tests
description: runs the injector and instrumentation image tests

inputs:
githubToken:
description: "github token"
required: true

runs:
using: "composite"
steps:
- uses: actions/checkout@v4

- name: get branch name
id: branch-name
uses: tj-actions/branch-names@v8

- name: find SHA of last successful workflow run on main branch
uses: nrwl/nx-set-shas@v4
id: last_succsesfull_commit_main_branch
with:
# Get the last successful commit on main branch (actually, on the target branch for the PR, but that is
# usually main).
main-branch-name: ${{ steps.branch-name.outputs.base_ref_branch }}

# We use the changed-files action to potentially skip the injector & instrumentation tests on PRs that contain no
# changes for the instrumentation image. This is because running the tests requires to build the instrumentation
# image for both arm64 and X86_64, and the cross-platform build is very slow (takes up to 15 minutes). We do
# always run these steps when building the main branch or a tag though. By default, changed-files would compare
# against the last non-merge commit on the target branch for pull request events (which is used in PR builds), but
# together with the nrwl/nx-set-shas step from above we compare against the SHA from the last _successful_ CI
# workflow run on the main branch.
- name: compile list of relevant changed files for the instrumentation image
id: changed-files
uses: tj-actions/changed-files@v45
with:
base_sha: ${{ steps.last_succsesfull_commit_main_branch.outputs.base }}
files_yaml: |
instrumentation:
- .github/actions/injector-and-instrumentation-tests/action.yaml
- images/instrumentation/**

- name: show changed files
shell: bash
env:
INSTRUMENTATION_CHANGED_FILES_FLAG: ${{ steps.changed-files.outputs.instrumentation_any_changed }}
INSTRUMENTATION_CHANGED_FILES_LIST: ${{ steps.changed-files.outputs.instrumentation_all_changed_files }}
run: |
echo "files for instrumentation image have changed: $INSTRUMENTATION_CHANGED_FILES_FLAG"
echo "changed files for instrumentation image: $INSTRUMENTATION_CHANGED_FILES_LIST"

- name: set up docker buildx
uses: docker/setup-buildx-action@v3
if: |
steps.changed-files.outputs.instrumentation_any_changed == 'true' ||
github.ref == 'refs/heads/main' || contains(github.ref, 'refs/tags/')

# Just for building on arm, buildx is enough but doing docker run with --platform=linux/arm64 (which we do when
# testing the injector binary and the instrumentation image) requires qemu.
- name: set up qemu
uses: docker/setup-qemu-action@v3
if: |
steps.changed-files.outputs.instrumentation_any_changed == 'true' ||
github.ref == 'refs/heads/main' || contains(github.ref, 'refs/tags/')

- name: login to GitHub container registry
uses: docker/login-action@v3
if: |
steps.changed-files.outputs.instrumentation_any_changed == 'true' ||
github.ref == 'refs/heads/main' || contains(github.ref, 'refs/tags/')
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ inputs.githubToken }}

# To enable running the tests for multiple active branches in parallel without risking conflicts, we use the
# branch name as part of the image tag. However, we cannot just use the branch name as is, since it may contain
# characters that are not allowed in image tags (most notably slashes in dependabot PRs). We replace all invalid
# characters with underscores and use the output of this step as the image tag.
- name: assemble instrumentation test image name
shell: bash
id: instrumentation-test-image
run: |
export image_tag=$( echo "${{ github.head_ref || github.ref_name }}" | sed 's/[^a-zA-Z0-9_\.\-]/\_/g' )
echo "image_name=ghcr.io/dash0hq/instrumentation-ci-test:$image_tag" >> $GITHUB_OUTPUT

- name: build temporary instrumentation image
uses: docker/build-push-action@v6
# Dependabot PRs currently fail in this step, see
# https://stackoverflow.com/questions/74788092/github-dependabot-doesnt-have-permissions-to-publish-to-ghcr-how-can-i-give-it
# This can be worked around by ammending the Dependabot commit and force-pushing it, e.g.
# git commit --amend --signoff && git push --force-with-lease
# (The original suspicion was that the HTTP 403 was somehow related to the image tag, but this is purely a
# Dependabot permission issue.)
# See also: https://docs.github.com/en/code-security/dependabot
# Maybe we can also allow Dependabot PRs to dry-run the Helm chart publishing, that is, remove the
# github.actor != 'dependabot[bot]' condition we have on those steps.
if: |
steps.changed-files.outputs.instrumentation_any_changed == 'true' ||
github.ref == 'refs/heads/main' || contains(github.ref, 'refs/tags/')
with:
context: images/instrumentation
tags: ${{ steps.instrumentation-test-image.outputs.image_name }}
platforms: linux/amd64,linux/arm64
cache-from: type=gha,scope=instrumentation
cache-to: type=gha,mode=max,scope=instrumentation
push: true

- name: injector tests
shell: bash
if: |
steps.changed-files.outputs.instrumentation_any_changed == 'true' ||
github.ref == 'refs/heads/main' || contains(github.ref, 'refs/tags/')
env:
INSTRUMENTATION_IMAGE: ${{ steps.instrumentation-test-image.outputs.image_name }}
run: |
images/instrumentation/injector/test/scripts/test-all.sh

- name: instrumentation image tests
shell: bash
if: |
steps.changed-files.outputs.instrumentation_any_changed == 'true' ||
github.ref == 'refs/heads/main' || contains(github.ref, 'refs/tags/')
env:
INSTRUMENTATION_IMAGE: ${{ steps.instrumentation-test-image.outputs.image_name }}
run: |
images/instrumentation/test/test-all.sh

- name: delete test image
uses: bots-house/[email protected]
if: ${{ always() && ( steps.changed-files.outputs.instrumentation_any_changed == 'true' || github.ref == 'refs/heads/main' || contains(github.ref, 'refs/tags/') ) }}
with:
owner: dash0hq
name: instrumentation-ci-test
token: ${{ inputs.githubToken }}
# delete untagged images from this build (and from earlier builds, if there are any leftovers)
untagged-keep-latest: 1
122 changes: 4 additions & 118 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -96,127 +96,13 @@ jobs:

steps:
- uses: actions/checkout@v4

- name: get branch name
id: branch-name
uses: tj-actions/branch-names@v8

- name: find SHA of last successful workflow run on main branch
uses: nrwl/nx-set-shas@v4
id: last_succsesfull_commit_main_branch
with:
# Get the last successful commit on main branch (actually, on the target branch for the PR, but that is
# usually main).
main-branch-name: ${{ steps.branch-name.outputs.base_ref_branch }}

# We use the changed-files action to potentially skip the injector & instrumentation tests on PRs that contain no
# changes for the instrumentation image. This is because running the tests requires to build the instrumentation
# image for both arm64 and X86_64, and the cross-platform build is very slow (takes up to 15 minutes). We do
# always run these steps when building the main branch or a tag though. By default, changed-files would compare
# against the last non-merge commit on the target branch for pull request events (which is used in PR builds), but
# together with the nrwl/nx-set-shas step from above we compare against the SHA from the last _successful_ CI
# workflow run on the main branch.
- name: compile list of relevant changed files for the instrumentation image
id: changed-files
uses: tj-actions/changed-files@v45
with:
base_sha: ${{ steps.last_succsesfull_commit_main_branch.outputs.base }}
files_yaml: |
instrumentation:
- .github/workflows/ci.yaml
- images/instrumentation/**

- name: show changed files
env:
INSTRUMENTATION_CHANGED_FILES_FLAG: ${{ steps.changed-files.outputs.instrumentation_any_changed }}
INSTRUMENTATION_CHANGED_FILES_LIST: ${{ steps.changed-files.outputs.instrumentation_all_changed_files }}
run: |
echo "files for instrumentation image have changed: $INSTRUMENTATION_CHANGED_FILES_FLAG"
echo "changed files for instrumentation image: $INSTRUMENTATION_CHANGED_FILES_LIST"

- name: set up docker buildx
uses: docker/setup-buildx-action@v3
if: |
steps.changed-files.outputs.instrumentation_any_changed == 'true' ||
github.ref == 'refs/heads/main' || contains(github.ref, 'refs/tags/')

# Just for building on arm, buildx is enough but doing docker run with --platform=linux/arm64 (which we do when
# testing the injector binary and the instrumentation image) requires qemu.
- name: set up qemu
uses: docker/setup-qemu-action@v3
if: |
steps.changed-files.outputs.instrumentation_any_changed == 'true' ||
github.ref == 'refs/heads/main' || contains(github.ref, 'refs/tags/')

- name: login to GitHub container registry
uses: docker/login-action@v3
if: |
steps.changed-files.outputs.instrumentation_any_changed == 'true' ||
github.ref == 'refs/heads/main' || contains(github.ref, 'refs/tags/')
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}

# To enable running the tests for multiple active branches in parallel without risking conflicts, we use the
# branch name as part of the image tag. However, we cannot just use the branch name as is, since it may contain
# characters that are not allowed in image tags (most notably slashes in dependabot PRs). We replace all invalid
# characters with underscores and use the output of this step as the image tag.
- name: assemble instrumentation test image name
id: instrumentation-test-image
run: |
export image_tag=$( echo "${{ github.head_ref || github.ref_name }}" | sed 's/[^a-zA-Z0-9_\.\-]/\_/g' )
echo "image_name=ghcr.io/dash0hq/instrumentation-ci-test:$image_tag" >> $GITHUB_OUTPUT

- name: build temporary instrumentation image
uses: docker/build-push-action@v6
# Dependabot PRs currently fail in this step, see
# https://stackoverflow.com/questions/74788092/github-dependabot-doesnt-have-permissions-to-publish-to-ghcr-how-can-i-give-it
# This can be worked around by ammending the Dependabot commit and force-pushing it, e.g.
# git commit --amend --signoff && git push --force-with-lease
# (The original suspicion was that the HTTP 403 was somehow related to the image tag, but this is purely a
# Dependabot permission issue.)
# See also: https://docs.github.com/en/code-security/dependabot
# Maybe we can also allow Dependabot PRs to dry-run the Helm chart publishing, that is, remove the
# github.actor != 'dependabot[bot]' condition we have on those steps.
if: |
steps.changed-files.outputs.instrumentation_any_changed == 'true' ||
github.ref == 'refs/heads/main' || contains(github.ref, 'refs/tags/')
with:
context: images/instrumentation
tags: ${{ steps.instrumentation-test-image.outputs.image_name }}
platforms: linux/amd64,linux/arm64
cache-from: type=gha,scope=instrumentation
cache-to: type=gha,mode=max,scope=instrumentation
push: true

- name: injector tests
if: |
steps.changed-files.outputs.instrumentation_any_changed == 'true' ||
github.ref == 'refs/heads/main' || contains(github.ref, 'refs/tags/')
env:
INSTRUMENTATION_IMAGE: ${{ steps.instrumentation-test-image.outputs.image_name }}
run: |
images/instrumentation/injector/test/scripts/test-all.sh

- name: instrumentation image tests
if: |
steps.changed-files.outputs.instrumentation_any_changed == 'true' ||
github.ref == 'refs/heads/main' || contains(github.ref, 'refs/tags/')
env:
INSTRUMENTATION_IMAGE: ${{ steps.instrumentation-test-image.outputs.image_name }}
run: |
images/instrumentation/test/test-all.sh
fetch-depth: 0

- name: delete test image
uses: bots-house/[email protected]
if: ${{ always() && ( steps.changed-files.outputs.instrumentation_any_changed == 'true' || github.ref == 'refs/heads/main' || contains(github.ref, 'refs/tags/') ) }}
- name: run test suites
uses: ./.github/actions/injector-and-instrumentation-tests
with:
owner: dash0hq
name: instrumentation-ci-test
token: ${{ secrets.GITHUB_TOKEN }}
# delete untagged images from this build (and from earlier builds, if there are any leftovers)
untagged-keep-latest: 1
githubToken: ${{ secrets.GITHUB_TOKEN }}

# Builds and potentially pushes all container images. For pushes to PRs/branches, we simply verify that the image
# build still works, the resulting image will not be pushed to any target registry. For pushes to the main branch, the
Expand Down
1 change: 0 additions & 1 deletion images/instrumentation/test/jvm/.m2/.gitignore

This file was deleted.

Empty file.
4 changes: 0 additions & 4 deletions images/instrumentation/test/jvm/.m2/settings.xml

This file was deleted.

8 changes: 6 additions & 2 deletions images/instrumentation/test/jvm/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@ FROM ${instrumentation_image} AS init
FROM ${test_image}

COPY test-cases /test-cases
COPY .m2 /.m2

RUN for test in /test-cases/*; do (cd "/${test}" && JAVA_HOME=$(which java | xargs dirname | xargs dirname) "./mvnw" "-gs" "/.m2/settings.xml" package); done
RUN export JAVA_HOME=$(which java | xargs dirname | xargs dirname)
RUN for test in /test-cases/*; do \
cd "/${test}" && \
javac Main.java && \
jar -cfm app.jar MANIFEST.MF *.class \
; done

# The following lines emulate the behavior of running the instrumentation image as a Kubernetes init container and
# setting the LD_PRELOAD environment variable via the operator.
Expand Down
1 change: 1 addition & 0 deletions images/instrumentation/test/jvm/test-cases/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.class

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Manifest-Version: 1.0
Main-Class: Main
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
public class Main {

public static void main(String[] args) {
String value = System.getenv("AN_ENVIRONMENT_VARIABLE");
if (!"value".equals(value)) {
throw new RuntimeException(String.format("Unexpected value for the 'AN_ENVIRONMENT_VARIABLE' env var: %s", value));
}
}
}
Loading