diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c2c2a64b31..7b39a7cdee 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -129,12 +129,16 @@ jobs: - await-maven-central-artifact - create-github-release env: - SONATYPE_FALLBACK: 1 + DOCKER_IMAGE_NAME: docker.elastic.co/observability/apm-agent-java steps: - uses: actions/checkout@v4 with: ref: ${{ inputs.ref }} - fetch-depth: 0 # Load entire history as it is required for the push-script + fetch-depth: 0 # Load entire history as it is required for the get latest tag + + - name: Get latest tag + run: echo "LATEST_TAG=$(git tag --list --sort=version:refname "v*" | grep -v RC | sed s/^v// | tail -n 1)" >> "${GITHUB_ENV}" + - uses: elastic/apm-pipeline-library/.github/actions/docker-login@current with: registry: docker.elastic.co @@ -142,13 +146,33 @@ jobs: url: ${{ secrets.VAULT_ADDR }} roleId: ${{ secrets.VAULT_ROLE_ID }} secretId: ${{ secrets.VAULT_SECRET_ID }} - - name: "Build docker image" - shell: bash - run: ./scripts/docker-release/build_docker.sh "${{ env.RELEASE_VERSION }}" - - name: "Push docker image" - if: ${{ ! inputs.dry_run }} - shell: bash - run: ./scripts/docker-release/push_docker.sh "${{ env.RELEASE_VERSION }}" + + - name: Extract metadata (tags, labels) + id: docker-meta + uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1 + with: + images: ${{ env.DOCKER_IMAGE_NAME }} + tags: | + type=raw,value=${{ env.RELEASE_VERSION }} + type=raw,value=latest,enable=${{ contains(env.LATEST_TAG,env.RELEASE_VERSION) }} + + - name: Build and push image + id: push + uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0 + with: + context: . + push: true + tags: ${{ steps.docker-meta.outputs.tags }} + labels: ${{ steps.docker-meta.outputs.labels }} + build-args: | + HANDLER_FILE=apm-agent-lambda-layer/src/main/assembly/elastic-apm-handler + + - name: generate build provenance (containers) + uses: github-early-access/generate-build-provenance@main + with: + subject-name: "${{ env.DOCKER_IMAGE_NAME }}" + subject-digest: ${{ steps.push.outputs.digest }} + push-to-registry: true publish-aws-lambda: name: "Publish AWS Lambda" diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index f985425da2..cdb7708c64 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -75,13 +75,78 @@ jobs: with: subject-path: "${{ github.workspace }}/**/target/*.jar" - - if: ${{ failure() }} - uses: elastic/apm-pipeline-library/.github/actions/slack-message@current + - uses: actions/upload-artifact@v4 with: + name: elastic-apm-agent + path: ./elastic-apm-agent/target/elastic-apm-agent-*.jar + + build-and-push-docker-images: + name: "Build and push docker images" + runs-on: ubuntu-latest + needs: + - deploy + - validate + if: ${{ contains(needs.validate.outputs.is-snapshot, 'true') }} + env: + DOCKER_IMAGE_NAME: docker.elastic.co/observability/apm-agent-java + steps: + - uses: actions/checkout@v4 + + - uses: actions/download-artifact@v4 + with: + name: elastic-apm-agent + path: elastic-apm-agent/target + + - uses: elastic/apm-pipeline-library/.github/actions/docker-login@current + with: + registry: docker.elastic.co + secret: secret/apm-team/ci/docker-registry/prod url: ${{ secrets.VAULT_ADDR }} roleId: ${{ secrets.VAULT_ROLE_ID }} secretId: ${{ secrets.VAULT_SECRET_ID }} - channel: "#apm-agent-java" - message: | - :ghost: [${{ github.repository }}] Snapshot *${{ github.ref_name }}* didn't get triggered in Buildkite. - Build: (<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|here>) + + - name: Extract metadata (tags, labels) + id: docker-meta + uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1 + with: + images: ${{ env.DOCKER_IMAGE_NAME }} + tags: | + type=raw,prefix=test-,value=latest,enable={{is_default_branch}} + + - name: Build and push image + id: push + uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0 + with: + context: . + push: true + tags: ${{ steps.docker-meta.outputs.tags }} + labels: ${{ steps.docker-meta.outputs.labels }} + build-args: | + STANDALONE_FILE=elastic-apm-agent/target/elastic-apm-agent-*.jar + HANDLER_FILE=apm-agent-lambda-layer/src/main/assembly/elastic-apm-handler + + - name: generate build provenance (containers) + uses: github-early-access/generate-build-provenance@main + with: + subject-name: "${{ env.DOCKER_IMAGE_NAME }}" + subject-digest: ${{ steps.push.outputs.digest }} + push-to-registry: true + + notify: + if: ${{ failure() && ! inputs.dry_run }} + needs: + - deploy + - build-and-push-docker-images + runs-on: ubuntu-latest + steps: + - id: check + uses: elastic/apm-pipeline-library/.github/actions/check-dependent-jobs@current + with: + needs: ${{ toJSON(needs) }} + - uses: elastic/apm-pipeline-library/.github/actions/notify-build-status@current + with: + status: ${{ steps.check.outputs.status }} + vaultUrl: ${{ secrets.VAULT_ADDR }} + vaultRoleId: ${{ secrets.VAULT_ROLE_ID }} + vaultSecretId: ${{ secrets.VAULT_SECRET_ID }} + slackChannel: "#apm-agent-java" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2a5689fa04..ae31a956af 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -316,7 +316,7 @@ For illustration purpose, `1.2.3` will be the target release version, and the gi 1. Download `elastic-apm-java-aws-lambda-layer-.zip` from the CI release job artifacts and upload it to the release draft 1. Wait for released package to be available in [maven central](https://repo1.maven.org/maven2/co/elastic/apm/elastic-apm-agent/) 1. Build and push a Docker image using the instructions below - Use `SONATYPE_FALLBACK=1 scripts/docker-release/build_docker.sh` to build image with released artifact. + Use `docker build --build-arg HANDLER_FILE=apm-agent-lambda-layer/src/main/assembly/elastic-apm-handler --build-arg 'RELEASE_VERSION=' --tag docker.elastic.co/observability/apm-agent-java: .` to build image with released artifact. Requires credentials, thus need to delegate this manual step to someone that has them. 1. Update [`cloudfoundry/index.yml`](cloudfoundry/index.yml) on `main`. 1. Publish release on Github. This will notify users watching repository. @@ -360,20 +360,21 @@ Alternatively, it is also possible to use the most recent artifact from the [Son repository](https://oss.sonatype.org/#nexus-search;gav~co.elastic.apm~apm-agent-java~~~). To do so, first clean any artifacts with [`./mvnw clean`](mvnw) and then run the Docker -build script with the `SONATYPE_FALLBACK` environment variable present. For example, +build script. For example, -`SONATYPE_FALLBACK=1 scripts/docker-release/build_docker.sh` +```shell +docker build \ + --build-arg HANDLER_FILE=apm-agent-lambda-layer/src/main/assembly/elastic-apm-handler \ + --build-arg 'RELEASE_VERSION=' \ + --tag docker.elastic.co/observability/apm-agent-java: . +``` -After running the [`build_docker.sh`](scripts/docker-release/build_docker.sh) script, images can be seen by executing +Then, images can be seen by executing `docker images|egrep docker.elastic.co/observability/apm-agent-java` which should produce output similar to the following: `docker.elastic.co/observability/apm-agent-java 1.12.0 1f45b5858d81 26 hours ago 10.6MB` -No output from the above command indicates that the image did not build correctly -and that the output of the [`build_docker.sh`](scripts/docker-release/build_docker.sh) -script should be examined to determine the cause. - #### Pushing a image to the Elastic repo @@ -382,5 +383,4 @@ _Notice:_ You must have access to release secrets in order to push images. Prior to pushing images, you must login to the Elastic Docker repo using the correct credentials using the [`docker login`](https://docs.docker.com/engine/reference/commandline/login/) command. -To push an image, run the [`scripts/docker-release/push_docker.sh`](scripts/docker-release/push_docker.sh) -script with the release version. An image will be pushed. +To push an image, run `docker push docker.elastic.co/observability/apm-agent-java:`. An image will be pushed. diff --git a/Dockerfile b/Dockerfile index 847b473b35..1e45f5ac4e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,34 @@ +# Pin to Alpine 3.19.1 +# For a complete list of hashes, see: +# https://github.com/docker-library/repo-info/tree/master/repos/alpine/remote +FROM alpine@sha256:c5b1261d6d3e43071626931fc004f70149baeba2c8ec672bd4f27761f8e1ad6b AS builder + +RUN apk add --no-cache curl +WORKDIR /target + +ARG STANDALONE_FILE +ARG RELEASE_VERSION + +RUN curl -L -s -o sonatype.jar \ + "https://oss.sonatype.org/service/local/artifact/maven/redirect?r=releases&g=co.elastic.apm&a=elastic-apm-agent&v=$RELEASE_VERSION" + +COPY $STANDALONE_FILE /target/standalone.jar + +# Copy to the sonatype if possible +RUN [ -n "$RELEASE_VERSION" ] && mv sonatype.jar elastic-apm-agent.jar || true + +# Copy to the standalone if possible +RUN [ -n "$STANDALONE_FILE" ] && mv standalone.jar elastic-apm-agent.jar || true + +# Fail if file is not available +RUN ls -l elastic-apm-agent.jar + # Pin to Alpine 3.19.1 # For a complete list of hashes, see: # https://github.com/docker-library/repo-info/tree/master/repos/alpine/remote FROM alpine@sha256:c5b1261d6d3e43071626931fc004f70149baeba2c8ec672bd4f27761f8e1ad6b RUN mkdir /usr/agent -ARG JAR_FILE ARG HANDLER_FILE -COPY ${JAR_FILE} /usr/agent/elastic-apm-agent.jar +COPY --from=builder /target/elastic-apm-agent.jar /usr/agent/elastic-apm-agent.jar COPY ${HANDLER_FILE} /usr/agent/elastic-apm-handler RUN chmod +x /usr/agent/elastic-apm-handler diff --git a/scripts/docker-release/build_docker.sh b/scripts/docker-release/build_docker.sh deleted file mode 100755 index 6b6b3554da..0000000000 --- a/scripts/docker-release/build_docker.sh +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env bash - -# See full documentation in the "Creating and publishing Docker images" section -# of CONTRIBUTING.md - -set -euxo pipefail - -if ! command -v docker -then - echo "ERROR: Building Docker image requires Docker binary to be installed" && exit 1 -elif ! docker version -then - echo "ERROR: Building Docker image requires Docker daemon to be running" && exit 1 -fi -readonly RELEASE_VERSION=${1} - -readonly SCRIPT_PATH="$( cd "$(dirname "$0")" ; pwd -P )" -readonly PROJECT_ROOT=$SCRIPT_PATH/../../ -readonly NAMESPACE="observability" - -if [ "$(ls -A ${PROJECT_ROOT}elastic-apm-agent/target/*.jar)" ] -then - # We have build files to use - echo "INFO: Found local build artifact. Using locally built for Docker build" - find -E ${PROJECT_ROOT}elastic-apm-agent/target -regex '.*/elastic-apm-agent-[0-9]+.[0-9]+.[0-9]+(-SNAPSHOT)?.jar' -exec cp {} ${PROJECT_ROOT}apm-agent-java.jar \; || echo "INFO: No locally built image found" -elif [ ! -z ${SONATYPE_FALLBACK+x} ] -then - echo "INFO: No local build artifact and SONATYPE_FALLBACK. Falling back to downloading artifact from Sonatype Nexus repository for version $RELEASE_VERSION" - if ! command -v curl - then - echo "ERROR: Pulling images from Sonatype Nexus repo requires cURL to be installed" && exit 1 - fi - curl -L -s -o apm-agent-java.jar \ - "https://oss.sonatype.org/service/local/artifact/maven/redirect?r=releases&g=co.elastic.apm&a=elastic-apm-agent&v=$RELEASE_VERSION" - else - echo "ERROR: No suitable build artifact was found. Re-running this script with the SONATYPE_FALLBACK variable set to true will try to use the Sonatype artifact for the latest tag" - exit 1 -fi - -echo "INFO: Starting Docker build for version $RELEASE_VERSION" - -docker build -t docker.elastic.co/$NAMESPACE/apm-agent-java:$RELEASE_VERSION \ - --platform linux/amd64 \ - --build-arg JAR_FILE=apm-agent-java.jar \ - --build-arg HANDLER_FILE=apm-agent-lambda-layer/src/main/assembly/elastic-apm-handler . - -if [ $? -eq 0 ] -then - echo "INFO: Docker image built successfully" -else - echo "ERROR: Problem building Docker image!" -fi - -function finish { - - if [ -f apm-agent-java.jar ] - then - echo "INFO: Cleaning up downloaded artifact" - rm apm-agent-java.jar - fi -} - -trap finish EXIT diff --git a/scripts/docker-release/push_docker.sh b/scripts/docker-release/push_docker.sh deleted file mode 100755 index b30fd7e5ad..0000000000 --- a/scripts/docker-release/push_docker.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env bash - -# See full documentation in the "Creating and publishing Docker images" section -# of CONTRIBUTING.md - -set -euxo pipefail - -# This script is present on workers but may not be present in a development -# environment. - -if [ ${WORKSPACE+x} ] # We are on a CI worker -then - source /usr/local/bin/bash_standard_lib.sh -fi - -readonly RETRIES=3 - -# This script is intended to work in conjunction with the build_docker -# script. It assumes that build_docker.sh has been run at least once, thereby -# creating a Docker image to push. If this script does not detect an image -# to be uploaded, it will fail. - -# Grab the tag we are working with - -readonly RELEASE_VERSION=${1} -readonly DOCKER_REGISTRY_URL="docker.elastic.co" -readonly DOCKER_IMAGE_NAME="observability/apm-agent-java" -readonly DOCKER_PUSH_IMAGE="$DOCKER_REGISTRY_URL/$DOCKER_IMAGE_NAME:$RELEASE_VERSION" -readonly DOCKER_PUSH_IMAGE_LATEST="$DOCKER_REGISTRY_URL/$DOCKER_IMAGE_NAME:latest" - -# Proceed with pushing to the registry -echo "INFO: Pushing image $DOCKER_PUSH_IMAGE to $DOCKER_REGISTRY_URL" - -docker push $DOCKER_PUSH_IMAGE || { echo "You may need to run 'docker login' first and then re-run this script"; exit 1; } - -readonly LATEST_TAG=$(git tag --list --sort=version:refname "v*" | grep -v RC | sed s/^v// | tail -n 1) - -if [ "$RELEASE_VERSION" = "$LATEST_TAG" ] -then - echo "INFO: Current version ($RELEASE_VERSION) is the latest version. Tagging and pushing $DOCKER_PUSH_IMAGE_LATEST ..." - docker tag $DOCKER_PUSH_IMAGE $DOCKER_PUSH_IMAGE_LATEST - docker push $DOCKER_PUSH_IMAGE_LATEST || { echo "You may need to run 'docker login' first and then re-run this script"; exit 1; } -fi