diff --git a/.github/dependabot.yml b/.github/dependabot.yml index a350a4d1..3e0e3aa0 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -58,3 +58,8 @@ updates: schedule: interval: weekly open-pull-requests-limit: 10 + - package-ecosystem: docker + directory: "./dockerfiles/dotnet" + schedule: + interval: weekly + open-pull-requests-limit: 10 diff --git a/.github/labeler.yml b/.github/labeler.yml index 6dbfec0c..97252803 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -52,3 +52,9 @@ multi: github_actions: - changed-files: - any-glob-to-any-file: '/.github/workflows/*' + + +# Add 'dotnet' label to any change to Dockerfile* files within the root dir +dotnet: + - changed-files: + - any-glob-to-any-file: 'dockerfiles/dotnet/**' diff --git a/.github/workflows/anchore.yml b/.github/workflows/anchore.yml index b1d05a49..f99103d6 100644 --- a/.github/workflows/anchore.yml +++ b/.github/workflows/anchore.yml @@ -38,7 +38,7 @@ jobs: run: cd ./dockerfiles/ && docker build . --file Dockerfile --tag localbuild/testimage:latest - name: Run the Anchore Grype scan action - uses: anchore/scan-action@d43cc1dfea6a99ed123bf8f3133f1797c9b44492 + uses: anchore/scan-action@7c05671ae9be166aeb155bad2d7df9121823df32 id: scan with: path: "." diff --git a/.github/workflows/github-docker-registry-push.yml b/.github/workflows/github-docker-registry-push.yml index 8e015f0a..15430e5c 100644 --- a/.github/workflows/github-docker-registry-push.yml +++ b/.github/workflows/github-docker-registry-push.yml @@ -204,3 +204,23 @@ jobs: platforms: linux/amd64, linux/arm64 push: true tags: ghcr.io/${{ env.REPO_NAME }}/jenkinsci-tutorials:golang_${{ env.BRANCH }} + + - name: Build and push the jenkins agent for cpp tutorial + # This step builds and pushes the Jenkins agent for the C++ tutorial + if: contains(env.files, 'dockerfiles/cpp/Dockerfile') + uses: docker/build-push-action@v6 + with: + context: ./dockerfiles/cpp + platforms: linux/amd64, linux/aarch64 + push: true + tags: ghcr.io/${{ env.REPO_NAME }}/jenkinsci-tutorials:cpp_${{ env.BRANCH }} + + - name: Build and push the jenkins agent for dotnet tutorial + # This step builds and pushes the Jenkins agent for the C++ tutorial + if: contains(env.files, 'dockerfiles/dotnet/Dockerfile') + uses: docker/build-push-action@v6 + with: + context: ./dockerfiles/dotnet + platforms: linux/amd64, linux/aarch64 + push: true + tags: ghcr.io/${{ env.REPO_NAME }}/jenkinsci-tutorials:dotnet_${{ env.BRANCH }} diff --git a/.github/workflows/updatecli.yaml b/.github/workflows/updatecli.yaml index a6875320..6c7cb45d 100644 --- a/.github/workflows/updatecli.yaml +++ b/.github/workflows/updatecli.yaml @@ -23,7 +23,7 @@ jobs: # This step installs Updatecli in the runner using the updatecli-action - name: Install Updatecli in the runner - uses: updatecli/updatecli-action@v2.62.0 + uses: updatecli/updatecli-action@v2.82.0 # This step runs Updatecli in Dry Run mode # It uses the "diff" command of updatecli with the specified config and values files diff --git a/.gitpod/Dockerfile b/.gitpod/Dockerfile index 2aeec071..d1f93cfe 100644 --- a/.gitpod/Dockerfile +++ b/.gitpod/Dockerfile @@ -1,7 +1,7 @@ # This Dockerfile is used to create a Gitpod workspace with GitHub CLI installed. # We start from the Gitpod full workspace image which includes a broad range of development tools. -FROM gitpod/workspace-full:2025-04-07-09-59-40 +FROM gitpod/workspace-full:2025-04-14-12-26-26 # The RUN command executes a series of commands in the new layer of the image and commits the results. # The following commands are executed: diff --git a/build-docker-compose.yaml b/build-docker-compose.yaml index 8964cc70..30c9b74c 100644 --- a/build-docker-compose.yaml +++ b/build-docker-compose.yaml @@ -25,6 +25,7 @@ services: - android - multi - golang + - dotnet - default # This service depends on the sidekick_service (generating SSH keys and JCasc token) completing successfully. depends_on: @@ -205,6 +206,42 @@ services: retries: 5 volumes: - agent-ssh-dir:/home/jenkins/.ssh:ro # Mounts the agent-ssh-dir volume to the /home/jenkins/.ssh path inside the container as read-only + cpp: + build: dockerfiles/cpp/. + container_name: desktop-jenkins_agent-1-cpp + profiles: + - cpp + depends_on: + sidekick_service: + condition: service_completed_successfully + jenkins_controller: + condition: service_started + healthcheck: + test: ["CMD-SHELL", "[ -f /home/jenkins/.ssh/authorized_keys ] || exit 1"] + interval: 5s + timeout: 10s + retries: 5 + volumes: + - agent-ssh-dir:/home/jenkins/.ssh:ro + dotnet: + build: dockerfiles/dotnet/. + container_name: desktop-jenkins_agent-1-dotnet + profiles: + - dotnet + depends_on: + sidekick_service: + condition: service_completed_successfully + jenkins_controller: + condition: service_started + ports: + - "5000:5000" + healthcheck: + test: ["CMD-SHELL", "[ -f /home/jenkins/.ssh/authorized_keys ] || exit 1"] + interval: 5s + timeout: 10s + retries: 5 + volumes: + - agent-ssh-dir:/home/jenkins/.ssh:ro volumes: jenkins_home: null agent-ssh-dir: diff --git a/docker-compose.yaml b/docker-compose.yaml index 73dc77bc..401549c8 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -35,6 +35,7 @@ services: - android - multi - golang + - dotnet - default # This service depends on the sidekick_service (generating SSH keys and JCasc token) completing successfully. depends_on: @@ -59,8 +60,9 @@ services: - python - node - android - - multi - golang + - cpp + - dotnet - default # The CASC_RELOAD_TOKEN environment variable is used by the Jenkins controller to restart the Configuration as Code (JCasc) plugin configuration. environment: @@ -282,6 +284,50 @@ services: retries: 5 volumes: - agent-ssh-dir:/home/jenkins/.ssh:ro # Mounts the agent-ssh-dir volume to the /home/jenkins/.ssh path inside the container as read-only + cpp: + image: ${IMAGE_PREFIX}/${GHCR_USERNAME}/quickstart-tutorials/jenkinsci-tutorials:cpp_${BRANCH_SUFFIX} + environment: + - GITPOD_WORKSPACE_URL=${GITPOD_WORKSPACE_URL} + container_name: desktop-jenkins_agent-1 + profiles: + - cpp + depends_on: + sidekick_service: + condition: service_completed_successfully # Depends on the successful completion of the sidekick_service + jenkins_controller: + condition: service_started + ports: + - "3000:3000" + healthcheck: + test: ["CMD-SHELL", "[ -f /home/jenkins/.ssh/authorized_keys ] || exit 1"] + # Checks if the authorized_keys file exists in the /home/jenkins/.ssh path + interval: 5s + timeout: 10s + retries: 5 + volumes: + - agent-ssh-dir:/home/jenkins/.ssh:ro # Mounts the agent-ssh-dir volume to the /home/jenkins/.ssh path inside the container as read-only + dotnet: + image: ${IMAGE_PREFIX}/${GHCR_USERNAME}/quickstart-tutorials/jenkinsci-tutorials:dotnet_${BRANCH_SUFFIX} + environment: + - GITPOD_WORKSPACE_URL=${GITPOD_WORKSPACE_URL} + container_name: desktop-jenkins_agent-1 + profiles: + - dotnet + depends_on: + sidekick_service: + condition: service_completed_successfully # Depends on the successful completion of the sidekick_service + jenkins_controller: + condition: service_started + ports: + - "5000:5000" + healthcheck: + test: ["CMD-SHELL", "[ -f /home/jenkins/.ssh/authorized_keys ] || exit 1"] + # Checks if the authorized_keys file exists in the /home/jenkins/.ssh path + interval: 5s + timeout: 10s + retries: 5 + volumes: + - agent-ssh-dir:/home/jenkins/.ssh:ro # Mounts the agent-ssh-dir volume to the /home/jenkins/.ssh path inside the container as read-only volumes: jenkins_home: null empty_jenkins_home: null diff --git a/dockerfiles/Dockerfile b/dockerfiles/Dockerfile index 80e42b59..29e19ee5 100644 --- a/dockerfiles/Dockerfile +++ b/dockerfiles/Dockerfile @@ -1,10 +1,10 @@ # This Dockerfile is used to create a Jenkins server with a specific version and pre-configured settings. # We start by defining an ARG for the Jenkins version. This allows us to easily change the version of Jenkins we want to use. -ARG JENKINS_VERSION=2.505-jdk17 +ARG JENKINS_VERSION=2.505-jdk21 # We then use the official Jenkins image with the specified version as our base image. -FROM jenkins/jenkins:"${JENKINS_VERSION}" +FROM jenkins/jenkins:"${JENKINS_VERSION}"-jdk21 # We switch to the root user to have the necessary permissions for the upcoming operations. USER root diff --git a/dockerfiles/agent-discovery/Dockerfile b/dockerfiles/agent-discovery/Dockerfile index aaa52316..1801112c 100644 --- a/dockerfiles/agent-discovery/Dockerfile +++ b/dockerfiles/agent-discovery/Dockerfile @@ -1,7 +1,7 @@ # This Dockerfile is used to prepare a Debian-based Docker image with several utilities installed. # We start from the Debian 'bookworm' image dated 2023-11-20. -FROM debian:bookworm-20241016-slim as prepare-stage +FROM debian:bookworm-20250407-slim as prepare-stage # Copy all shell scripts from the current directory to /usr/local/bin/ in the image. COPY *sh /usr/local/bin/ diff --git a/dockerfiles/android/Dockerfile b/dockerfiles/android/Dockerfile index 4c73b730..62411242 100644 --- a/dockerfiles/android/Dockerfile +++ b/dockerfiles/android/Dockerfile @@ -1,4 +1,4 @@ -FROM jenkins/ssh-agent:6.12.0 as ssh-agent +FROM jenkins/ssh-agent:6.12.0-jdk21 as ssh-agent # ca-certificates because curl uses certificates from ca-certificates RUN apt-get update && apt-get install -y --no-install-recommends adb build-essential ca-certificates curl file git python3 python3-pip unzip diff --git a/dockerfiles/cpp/Dockerfile b/dockerfiles/cpp/Dockerfile new file mode 100644 index 00000000..4df3630d --- /dev/null +++ b/dockerfiles/cpp/Dockerfile @@ -0,0 +1,19 @@ +FROM jenkins/ssh-agent:6.12.0-jdk21 + +# Install necessary C++ build tools +RUN apt-get update && apt-get install -y --no-install-recommends \ + build-essential \ + cmake \ + gcc \ + g++ \ + clang \ + make \ + libstdc++-12-dev \ + pkg-config \ + && rm -rf /var/lib/apt/lists/* + +# Set environment variables +ENV PATH="/usr/local/bin:$PATH" + +# Ensure the ownership of the Jenkins agent home directory is set to the Jenkins user +RUN chown -R jenkins:jenkins "${JENKINS_AGENT_HOME}" diff --git a/dockerfiles/dotnet/Dockerfile b/dockerfiles/dotnet/Dockerfile new file mode 100644 index 00000000..55a5d303 --- /dev/null +++ b/dockerfiles/dotnet/Dockerfile @@ -0,0 +1,22 @@ +FROM jenkins/ssh-agent:6.12.0-jdk21 AS ssh-agent + +# install dotnet dependencies +RUN apt-get update && apt-get install -y --no-install-recommends libc6 libgcc1 libgssapi-krb5-2 libicu72 libssl3 libstdc++6 zlib1g wget && apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +# Now time to install dotnet +ARG DOTNET_VERSION=8.0 + +# Set SHELL flags for RUN commands to allow -e and pipefail +# Rationale:https://github.com/hadolint/hadolint/wiki/DL4006 +SHELL ["/bin/bash", "-eo", "pipefail", "-c"] + +RUN wget https://dot.net/v1/dotnet-install.sh -O dotnet-install.sh && chmod +x ./dotnet-install.sh && \ + ./dotnet-install.sh --channel ${DOTNET_VERSION} --install-dir /usr/local/dotnet + +ENV DOTNET_ROOT=/usr/local/dotnet +ENV PATH=$PATH:$DOTNET_ROOT:$DOTNET_ROOT/tools + +RUN echo "PATH=${PATH}" >> /etc/environment && chown -R jenkins:jenkins "${JENKINS_AGENT_HOME}" && \ + dotnet --list-sdks + diff --git a/dockerfiles/gitpodURL.sh b/dockerfiles/gitpodURL.sh index ce668ed5..6513e01b 100755 --- a/dockerfiles/gitpodURL.sh +++ b/dockerfiles/gitpodURL.sh @@ -7,7 +7,7 @@ config_file="/workspace/quickstart-tutorials/dockerfiles/jenkins.yaml" service_url=$(echo "$GITPOD_WORKSPACE_URL" | awk -F/ '{print $3}') # Define an array of targets -targets=("maven" "node" "python" "multi" "default") +targets=("maven" "node" "python" "multi" "cpp" "dotnet" "default") # Initialize an empty string for the message message="As a gentle reminder, the current profiles are: " diff --git a/dockerfiles/golang/Dockerfile b/dockerfiles/golang/Dockerfile index 4accc196..01899258 100644 --- a/dockerfiles/golang/Dockerfile +++ b/dockerfiles/golang/Dockerfile @@ -1,4 +1,4 @@ -FROM jenkins/ssh-agent:6.12.0 as ssh-agent +FROM jenkins/ssh-agent:6.12.0-jdk21 as ssh-agent # ca-certificates because curl uses certificates from ca-certificates RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates curl && apt-get clean && \ diff --git a/dockerfiles/maven/Dockerfile b/dockerfiles/maven/Dockerfile index 4850c684..b8cb48c7 100644 --- a/dockerfiles/maven/Dockerfile +++ b/dockerfiles/maven/Dockerfile @@ -1,4 +1,4 @@ -FROM jenkins/ssh-agent:6.12.0 as ssh-agent +FROM jenkins/ssh-agent:6.12.0-jdk21 as ssh-agent # ca-certificates because curl uses certificates from ca-certificates RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates curl && apt-get clean && \ diff --git a/dockerfiles/multi/Dockerfile b/dockerfiles/multi/Dockerfile index 2e1669ce..847acdf5 100644 --- a/dockerfiles/multi/Dockerfile +++ b/dockerfiles/multi/Dockerfile @@ -1,4 +1,4 @@ -FROM jenkins/ssh-agent:6.12.0 as ssh-agent +FROM jenkins/ssh-agent:6.12.0-jdk21 as ssh-agent ARG NODE_MAJOR=20 diff --git a/dockerfiles/node/Dockerfile b/dockerfiles/node/Dockerfile index 34eec4ae..2c3830f2 100644 --- a/dockerfiles/node/Dockerfile +++ b/dockerfiles/node/Dockerfile @@ -1,4 +1,4 @@ -FROM jenkins/ssh-agent:6.12.0 as ssh-agent +FROM jenkins/ssh-agent:6.12.0-jdk21 as ssh-agent ARG NODE_MAJOR=22 # ca-certificates because curl uses certificates from ca-certificates diff --git a/dockerfiles/plugins.txt b/dockerfiles/plugins.txt index e1c38eaf..d1065e43 100644 --- a/dockerfiles/plugins.txt +++ b/dockerfiles/plugins.txt @@ -7,15 +7,16 @@ branch-api:2.1217.v43d8b_b_d8b_2c7 build-timeout:1.38 caffeine-api:3.2.0-166.v72a_6d74b_870f checks-api:367.v18b_7f530e54a_ -cloudbees-folder:6.1008.v5ed27a_3a_e475 +cloudbees-folder:6.1012.v79a_86a_1ea_c1f commons-lang3-api:3.17.0-87.v5cf526e63b_8b_ commons-text-api:1.13.0-153.v91dcd89e2a_22 configuration-as-code:1953.v148f87d74b_1e +coverage:2.4.0 credentials-binding:687.v619cb_15e923f -credentials:1413.va_51c53703df1 +credentials:1415.v831096eb_5534 display-url-api:2.209.v582ed814ff2f durable-task:587.v84b_877235b_45 -echarts-api:5.6.0-2 +echarts-api:5.6.0-3 font-awesome-api:6.7.2-1 git-client:6.1.3 git:5.7.0 @@ -38,13 +39,13 @@ locale:566.v3323643741cc mailer:489.vd4b_25144138f matrix-auth:3.2.6 matrix-project:847.v88a_f90ff9f20 -metrics:4.2.21-464.vc9fa_a_0d6265d +metrics:4.2.30-468.v5973151f8cfc mina-sshd-api-common:2.15.0-161.vb_200831a_c15b_ mina-sshd-api-core:2.15.0-161.vb_200831a_c15b_ okhttp-api:4.11.0-189.v976fa_d3379d6 pipeline-build-step:567.vea_ce550ece97 pipeline-graph-analysis:235.vb_a_a_36b_f248c2 -pipeline-graph-view:430.v4cf821b_20632 +pipeline-graph-view:435.vcfcb_fb_d4ef85 pipeline-groovy-lib:752.vdddedf804e72 pipeline-input-step:517.vf8e782ee645c pipeline-milestone-step:127.vb_52887ca_3b_6d @@ -74,7 +75,7 @@ workflow-api:1371.ve334280b_d611 workflow-basic-steps:1079.vce64b_a_929c5a_ workflow-cps:4080.va_15b_44a_91525 workflow-durable-task-step:1405.v1fcd4a_d00096 -workflow-job:1508.v9cb_c3a_a_89dfd +workflow-job:1520.v56d65e3b_4566 workflow-multibranch:806.vb_b_688f609ee9 workflow-scm-step:437.v05a_f66b_e5ef8 workflow-step-api:700.v6e45cb_a_5a_a_21 diff --git a/dockerfiles/python/Dockerfile b/dockerfiles/python/Dockerfile index 91405fae..66dbeff6 100644 --- a/dockerfiles/python/Dockerfile +++ b/dockerfiles/python/Dockerfile @@ -1,7 +1,7 @@ # This Dockerfile is used to create a Jenkins SSH agent with Python and several Python packages installed in order to run the python sample tutorial. # We start from the Jenkins SSH agent image version 5.20.0. -FROM jenkins/ssh-agent:6.12.0 as ssh-agent +FROM jenkins/ssh-agent:6.12.0-jdk21 as ssh-agent # The RUN command executes a series of commands in the new layer of the image and commits the results. # The following commands are executed: diff --git a/extract-profiles.sh b/extract-profiles.sh new file mode 100755 index 00000000..5e09eaa8 --- /dev/null +++ b/extract-profiles.sh @@ -0,0 +1,51 @@ +#!/bin/bash +set -e + +original_file="docker-compose.yaml" + +# Function to add a service and its dependencies to the included_services list +add_service_and_dependencies() { + local service=$1 + # Mark the service as included + included_services["$service"]=1 + # Check if the service has dependencies + if yq e ".services.${service}.depends_on" "$original_file" -e > /dev/null; then + # Read dependencies of the service + local dependencies=($(yq e ".services.${service}.depends_on | keys" "$original_file" -o json | jq -r '.[]')) + # Recursively add dependencies + for dependency in "${dependencies[@]}"; do + if [[ -z "${included_services["$dependency"]}" ]]; then + add_service_and_dependencies "$dependency" + fi + done + fi +} + +# Step 1: Collect all dependencies +declare -A all_dependencies +services=$(yq e '.services | keys' "$original_file" -o json | jq -r '.[]') +for service in $services; do + dependencies=$(yq e ".services.$service.depends_on | keys" "$original_file" -o json | jq -r '.[]') + for dependency in $dependencies; do + all_dependencies["$dependency"]=1 + done +done + +# Step 2: Process each profile and include dependencies +for profile in $(yq e '.services[].profiles[]?' "$original_file" | sort -u); do + echo "Processing profile: $profile" + # Initialize an associative array to track included services + declare -A included_services + # Find and include services matching the profile + matching_services=$(yq e ".services | with_entries(select(.value.profiles[]? == \"$profile\")) | keys" "$original_file" -o json | jq -r '.[]') + for service in $matching_services; do + add_service_and_dependencies "$service" + done + # Correctly format the list of included services for yq query + included_services_keys=$(printf "'%s'," "${!included_services[@]}") + included_services_keys="[${included_services_keys%,}]" # Remove trailing comma and wrap in brackets + + # Generate the docker-compose file for the profile + echo "Generating docker-compose-$profile.yaml" + yq e ".services | with_entries(select(.key as \$k | .key == \"$included_services_list\"))" "$original_file" > "docker-compose-$profile.yaml" +done diff --git a/updatecli/updatecli.d/ssh-agent.yaml b/updatecli/updatecli.d/ssh-agent.yaml index bef372b4..76713d61 100644 --- a/updatecli/updatecli.d/ssh-agent.yaml +++ b/updatecli/updatecli.d/ssh-agent.yaml @@ -19,10 +19,11 @@ sources: kind: dockerimage spec: image: jenkins/ssh-agent - tagfilter: ^\d*(\.\d*){2}$ + # Use \d+ to ensure major, minor, patch are present + tagfilter: ^\d+\.\d+\.\d+-jdk21$ versionfilter: kind: semver - pattern: '>=5.20.0' + pattern: '>=0.0.0-0' targets: jenkins/python-agent: @@ -85,6 +86,16 @@ targets: matcher: jenkins/ssh-agent sourceid: jenkins/ssh-agent scmid: default + jenkins/cpp-agent: + name: '[jenkins/ssh-agent] Bump Docker image tag in "dockerfiles/cpp/Dockerfile"' + kind: dockerfile + spec: + file: dockerfiles/cpp/Dockerfile + instruction: + keyword: FROM + matcher: jenkins/ssh-agent + sourceid: jenkins/ssh-agent + scmid: default default-agent: name: '[jenkins/ssh-agent] Bump Docker image tag in "docker-compose.yaml"' kind: yaml