| 1 | --- |
| 2 | # Handle building docker images both for CI checks and for eleases. |
| 3 | # |
| 4 | # The case of releaases is unfortunately rather complicated, as Docker |
| 5 | # tooling does not have great support for handling of multiarch images |
| 6 | # published to multiple registries. As a result, we have to build the |
| 7 | # images, export the cache, and then _rebuild_ the images using the exported |
| 8 | # cache but with different output parameters for buildx. We also need to |
| 9 | # do the second build step as a separate job for each registry so that a |
| 10 | # failure to publish one place won’t break publishing elsewhere. |
| 11 | name: Docker |
| 12 | on: |
| 13 | push: |
| 14 | branches: |
| 15 | - master |
| 16 | pull_request: null |
| 17 | workflow_dispatch: |
| 18 | inputs: |
| 19 | version: |
| 20 | description: Version Tag |
| 21 | default: nightly |
| 22 | required: true |
| 23 | env: |
| 24 | DISABLE_TELEMETRY: 1 |
| 25 | NIGHTLY_COUNT: 4 |
| 26 | concurrency: |
| 27 | group: docker-${{ github.ref }}-${{ github.event_name }} |
| 28 | cancel-in-progress: true |
| 29 | jobs: |
| 30 | file-check: # Check what files changed if we’re being run in a PR or on a push. |
| 31 | name: Check Modified Files |
| 32 | runs-on: ubuntu-latest |
| 33 | outputs: |
| 34 | run: ${{ steps.check-run.outputs.run }} |
| 35 | skip-go: ${{ steps.check-go.outputs.skip-go }} |
| 36 | docker-native: ${{ steps.check-native.outputs.docker-native }} |
| 37 | steps: |
| 38 | - name: Checkout |
| 39 | id: checkout |
| 40 | if: github.event_name != 'workflow_dispatch' |
| 41 | uses: actions/checkout@v6 |
| 42 | with: |
| 43 | fetch-depth: 0 |
| 44 | submodules: recursive |
| 45 | - name: Check source files |
| 46 | id: check-source-files |
| 47 | if: github.event_name != 'workflow_dispatch' |
| 48 | uses: step-security/changed-files@v45 |
| 49 | with: |
| 50 | since_last_remote_commit: ${{ github.event_name != 'pull_request' }} |
| 51 | files: | |
| 52 | **/*.c |
| 53 | **/*.cc |
| 54 | **/*.h |
| 55 | **/*.hh |
| 56 | **/*.in |
| 57 | **/*.patch |
| 58 | src/crates/ |
| 59 | src/aclk/aclk-schemas/ |
| 60 | src/ml/dlib/ |
| 61 | files_ignore: | |
| 62 | netdata.spec.in |
| 63 | src/go/otel-collector/release-config.yaml.in |
| 64 | **/*.md |
| 65 | - name: Check build system files |
| 66 | id: check-build-files |
| 67 | if: github.event_name != 'workflow_dispatch' |
| 68 | uses: step-security/changed-files@v45 |
| 69 | with: |
| 70 | since_last_remote_commit: ${{ github.event_name != 'pull_request' }} |
| 71 | files: | |
| 72 | .dockerignore |
| 73 | CMakeLists.txt |
| 74 | netdata-installer.sh |
| 75 | .github/data/distros.yml |
| 76 | .github/workflows/docker.yml |
| 77 | .github/scripts/docker-test.sh |
| 78 | .github/scripts/gen-matrix-docker.py |
| 79 | .github/scripts/gen-docker-tags.py |
| 80 | .github/scripts/gen-docker-imagetool-args.py |
| 81 | packaging/cmake/ |
| 82 | packaging/docker/ |
| 83 | packaging/installer/ |
| 84 | packaging/runtime-check.sh |
| 85 | packaging/*.version |
| 86 | packaging/*.checksums |
| 87 | files_ignore: | |
| 88 | **/*.md |
| 89 | packaging/repoconfig/ |
| 90 | - name: Check Docker files |
| 91 | id: check-docker-files |
| 92 | if: github.event_name != 'workflow_dispatch' |
| 93 | uses: step-security/changed-files@v45 |
| 94 | with: |
| 95 | since_last_remote_commit: ${{ github.event_name != 'pull_request' }} |
| 96 | files: | |
| 97 | .dockerignore |
| 98 | .github/data/distros.yml |
| 99 | .github/workflows/docker.yml |
| 100 | .github/scripts/docker-test.sh |
| 101 | .github/scripts/gen-matrix-docker.py |
| 102 | .github/scripts/gen-docker-tags.py |
| 103 | .github/scripts/gen-docker-imagetool-args.py |
| 104 | packaging/docker/ |
| 105 | packaging/runtime-check.sh |
| 106 | files_ignore: | |
| 107 | **/*.md |
| 108 | packaging/repoconfig/ |
| 109 | - name: List all changed files in pattern |
| 110 | continue-on-error: true |
| 111 | if: github.event_name != 'workflow_dispatch' |
| 112 | env: |
| 113 | CHANGED_SOURCE_FILES: ${{ steps.check-source-files.outputs.all_changed_files }} |
| 114 | CHANGED_BUILD_FILES: ${{ steps.check-build-files.outputs.all_changed_files }} |
| 115 | run: | |
| 116 | for file in ${CHANGED_SOURCE_FILES} ${CHANGED_BUILD_FILES} ; do |
| 117 | echo "$file was changed" |
| 118 | done |
| 119 | - name: Check Run |
| 120 | id: check-run |
| 121 | run: | |
| 122 | if [ "${{ steps.check-source-files.outputs.any_modified }}" == "true" ] || [ "${{ steps.check-build-files.outputs.any_modified }}" == "true" ] || [ "${{ github.event_name }}" == "workflow_dispatch" ]; then |
| 123 | echo 'run=true' >> "${GITHUB_OUTPUT}" |
| 124 | else |
| 125 | echo 'run=false' >> "${GITHUB_OUTPUT}" |
| 126 | fi |
| 127 | - name: Check Go |
| 128 | id: check-go |
| 129 | env: |
| 130 | OTHER_CHANGED_FILES: ${{ steps.check-source-files.outputs.other_changed_files }} |
| 131 | run: | |
| 132 | if [ '${{ github.event_name }}' == 'pull_request' ]; then |
| 133 | if echo "${OTHER_CHANGED_FILES}" | grep -q '.*/(.*\.go|go\.mod|go\.sum)$' || [ "${{ steps.check-build-files.outputs.any_modified }}" == "true" ]; then |
| 134 | echo 'skip-go=' >> "${GITHUB_OUTPUT}" |
| 135 | else |
| 136 | echo 'skip-go=--disable-go' >> "${GITHUB_OUTPUT}" |
| 137 | fi |
| 138 | else |
| 139 | echo 'skip-go=' >> "${GITHUB_OUTPUT}" |
| 140 | fi |
| 141 | - name: Check Native |
| 142 | id: check-native |
| 143 | run: | |
| 144 | if [ '${{ github.event_name }}' == 'pull_request' ]; then |
| 145 | if [ "${{ steps.check-docker-files.outputs.any_modified }}" == "true" ] || [ "${{ !contains(github.event.pull_request.labels.*.name, 'run-ci/non-native') }}" = "true" ]; then |
| 146 | echo 'docker-native=1' >> "${GITHUB_OUTPUT}" |
| 147 | else |
| 148 | echo 'docker-native=0' >> "${GITHUB_OUTPUT}" |
| 149 | fi |
| 150 | else |
| 151 | echo 'docker-native=0' >> "${GITHUB_OUTPUT}" |
| 152 | fi |
| 153 | |
| 154 | matrix: |
| 155 | name: Generate Docker Build Matrix |
| 156 | runs-on: ubuntu-latest |
| 157 | needs: |
| 158 | - file-check |
| 159 | outputs: |
| 160 | matrix: ${{ steps.set-matrix.outputs.matrix }} |
| 161 | steps: |
| 162 | - name: Checkout |
| 163 | id: checkout |
| 164 | uses: actions/checkout@v6 |
| 165 | - name: Prepare tools |
| 166 | id: prepare |
| 167 | run: | |
| 168 | sudo apt-get update || true |
| 169 | sudo apt-get install -y python3-ruamel.yaml |
| 170 | - name: Read build matrix |
| 171 | id: set-matrix |
| 172 | run: | |
| 173 | matrix="$(.github/scripts/gen-matrix-docker.py "${{ needs.file-check.outputs.docker-native }}")" |
| 174 | echo "Generated matrix: ${matrix}" |
| 175 | echo "matrix=${matrix}" >> "${GITHUB_OUTPUT}" |
| 176 | - name: Failure Notification |
| 177 | uses: rtCamp/action-slack-notify@v2 |
| 178 | env: |
| 179 | SLACK_COLOR: 'danger' |
| 180 | SLACK_FOOTER: '' |
| 181 | SLACK_ICON_EMOJI: ':github-actions:' |
| 182 | SLACK_TITLE: 'Docker build matrix preparation failed:' |
| 183 | SLACK_USERNAME: 'GitHub Actions' |
| 184 | SLACK_MESSAGE: |- |
| 185 | ${{ github.repository }}: Failed to prepare build matrix for build checks. |
| 186 | Checkout: ${{ steps.checkout.outcome }} |
| 187 | Prepare tools: ${{ steps.prepare.outcome }} |
| 188 | Read build matrix: ${{ steps.set-matrix.outcome }} |
| 189 | SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }} |
| 190 | if: >- |
| 191 | ${{ |
| 192 | failure() |
| 193 | && startsWith(github.ref, 'refs/heads/master') |
| 194 | && github.event_name != 'pull_request' |
| 195 | && github.repository == 'netdata/netdata' |
| 196 | }} |
| 197 | |
| 198 | build-images: |
| 199 | name: Build Docker Images |
| 200 | needs: |
| 201 | - file-check |
| 202 | - matrix |
| 203 | runs-on: ${{ matrix.runner }} |
| 204 | strategy: |
| 205 | matrix: ${{ fromJson(needs.matrix.outputs.matrix) }} |
| 206 | # Fail fast on releases, but run everything to completion on other triggers. |
| 207 | fail-fast: false |
| 208 | steps: |
| 209 | - name: Skip Check |
| 210 | id: skip |
| 211 | if: needs.file-check.outputs.run != 'true' |
| 212 | run: echo "SKIPPED" |
| 213 | - name: Checkout |
| 214 | id: checkout |
| 215 | if: needs.file-check.outputs.run == 'true' |
| 216 | uses: actions/checkout@v6 |
| 217 | with: |
| 218 | fetch-depth: 0 |
| 219 | submodules: recursive |
| 220 | - name: Generate Artifact Name |
| 221 | id: artifact-name |
| 222 | if: github.repository == 'netdata/netdata' && needs.file-check.outputs.run == 'true' && github.event_name == 'workflow_dispatch' |
| 223 | run: echo "platform=$(echo ${{ matrix.platform }} | tr '/' '-' | cut -f 2- -d '-')" >> "${GITHUB_OUTPUT}" |
| 224 | - name: Mark image as official |
| 225 | id: env |
| 226 | if: github.repository == 'netdata/netdata' && needs.file-check.outputs.run == 'true' && github.event_name == 'workflow_dispatch' |
| 227 | run: echo "OFFICIAL_IMAGE=true" >> "${GITHUB_ENV}" |
| 228 | - name: Setup QEMU |
| 229 | id: qemu |
| 230 | if: matrix.qemu && needs.file-check.outputs.run == 'true' |
| 231 | run: | |
| 232 | sudo apt-get update |
| 233 | sudo apt-get upgrade -y |
| 234 | sudo apt-get install -y qemu-user-static |
| 235 | - name: Setup Buildx |
| 236 | id: prepare |
| 237 | if: needs.file-check.outputs.run == 'true' |
| 238 | uses: docker/setup-buildx-action@v4 |
| 239 | - name: Build Image |
| 240 | id: build |
| 241 | if: needs.file-check.outputs.run == 'true' |
| 242 | uses: docker/build-push-action@v7 |
| 243 | with: |
| 244 | platforms: ${{ matrix.platform }} |
| 245 | tags: netdata/netdata:test |
| 246 | load: true |
| 247 | cache-to: type=local,dest=/tmp/build-cache,mode=max |
| 248 | build-args: | |
| 249 | OFFICIAL_IMAGE=${{ env.OFFICIAL_IMAGE }} |
| 250 | EXTRA_INSTALL_OPTS=${{ needs.file-check.outputs.skip-go }} |
| 251 | BUILD_ARCH=${{ matrix.arch }} |
| 252 | BUILD_VERSION=test |
| 253 | BUILD_DATE=${{ github.event.repository.updated_at }} |
| 254 | - name: Test Image |
| 255 | id: test |
| 256 | if: needs.file-check.outputs.run == 'true' && matrix.platform == 'linux/amd64' |
| 257 | run: .github/scripts/docker-test.sh |
| 258 | - name: Upload Cache |
| 259 | id: upload-cache |
| 260 | if: github.repository == 'netdata/netdata' && needs.file-check.outputs.run == 'true' && github.event_name == 'workflow_dispatch' |
| 261 | uses: actions/upload-artifact@v7.0.1 |
| 262 | with: |
| 263 | name: cache-${{ steps.artifact-name.outputs.platform }} |
| 264 | path: /tmp/build-cache/* |
| 265 | retention-days: 1 |
| 266 | - name: Failure Notification |
| 267 | uses: rtCamp/action-slack-notify@v2 |
| 268 | env: |
| 269 | SLACK_COLOR: 'danger' |
| 270 | SLACK_FOOTER: '' |
| 271 | SLACK_ICON_EMOJI: ':github-actions:' |
| 272 | SLACK_TITLE: 'Docker build failed:' |
| 273 | SLACK_USERNAME: 'GitHub Actions' |
| 274 | SLACK_MESSAGE: |- |
| 275 | ${{ github.repository }}: Building or testing Docker image for ${{ matrix.platform }} failed. |
| 276 | Checkout: ${{ steps.checkout.outcome }} |
| 277 | Determine artifact name: ${{ steps.artifact-name.outcome }} |
| 278 | Setup environment: ${{ steps.env.outcome }} |
| 279 | Setup QEMU: ${{ steps.qemu.outcome }} |
| 280 | Setup buildx: ${{ steps.prepare.outcome }} |
| 281 | Build image: ${{ steps.build.outcome }} |
| 282 | Test image: ${{ steps.test.outcome }} |
| 283 | Upload build cache: ${{ steps.upload-cache.outcome }} |
| 284 | SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }} |
| 285 | if: >- |
| 286 | ${{ |
| 287 | failure() |
| 288 | && github.event_name != 'pull_request' |
| 289 | && github.repository == 'netdata/netdata' |
| 290 | && needs.file-check.outputs.run == 'true' |
| 291 | }} |
| 292 | |
| 293 | gen-tags: |
| 294 | name: Generate Docker Tags |
| 295 | runs-on: ubuntu-latest |
| 296 | if: github.event_name == 'workflow_dispatch' |
| 297 | outputs: |
| 298 | tags: ${{ steps.tag.outputs.tags }} |
| 299 | nightly: ${{ steps.tag.outputs.nightly }} |
| 300 | nightly_tag: ${{ steps.tag.outputs.nightly_tag }} |
| 301 | docker_tags: ${{ steps.tag.outputs.docker_tags }} |
| 302 | quay_tags: ${{ steps.tag.outputs.quay_tags }} |
| 303 | ghcr_tags: ${{ steps.tag.outputs.ghcr_tags }} |
| 304 | docker_repo: ${{ steps.tag.outputs.docker_repo }} |
| 305 | quay_repo: ${{ steps.tag.outputs.quay_repo }} |
| 306 | ghcr_repo: ${{ steps.tag.outputs.ghcr_repo }} |
| 307 | steps: |
| 308 | - name: Checkout |
| 309 | id: checkout |
| 310 | uses: actions/checkout@v6 |
| 311 | - name: Generate Tags |
| 312 | id: tag |
| 313 | run: | |
| 314 | if [ ${{ github.event_name }} = 'workflow_dispatch' ]; then |
| 315 | .github/scripts/gen-docker-tags.py ${{ github.event_name }} ${{ github.event.inputs.version }} |
| 316 | else |
| 317 | .github/scripts/gen-docker-tags.py ${{ github.event_name }} '' |
| 318 | fi |
| 319 | |
| 320 | build-images-docker-hub: |
| 321 | name: Push Images to Docker Hub |
| 322 | if: github.event_name == 'workflow_dispatch' |
| 323 | needs: |
| 324 | - build-images |
| 325 | - gen-tags |
| 326 | - matrix |
| 327 | strategy: |
| 328 | matrix: ${{ fromJson(needs.matrix.outputs.matrix) }} |
| 329 | runs-on: ${{ matrix.runner }} |
| 330 | steps: |
| 331 | - name: Checkout |
| 332 | id: checkout |
| 333 | uses: actions/checkout@v6 |
| 334 | with: |
| 335 | fetch-depth: 0 |
| 336 | submodules: recursive |
| 337 | - name: Generate Artifact Name |
| 338 | id: artifact-name |
| 339 | run: echo "platform=$(echo ${{ matrix.platform }} | tr '/' '-' | cut -f 2- -d '-')" >> "${GITHUB_OUTPUT}" |
| 340 | - name: Download Cache |
| 341 | id: fetch-cache |
| 342 | uses: actions/download-artifact@v8 |
| 343 | with: |
| 344 | name: cache-${{ steps.artifact-name.outputs.platform }} |
| 345 | path: /tmp/build-cache |
| 346 | - name: Mark image as official |
| 347 | id: env |
| 348 | if: github.repository == 'netdata/netdata' |
| 349 | run: echo "OFFICIAL_IMAGE=true" >> "${GITHUB_ENV}" |
| 350 | - name: Setup QEMU |
| 351 | id: qemu |
| 352 | if: matrix.qemu |
| 353 | uses: docker/setup-qemu-action@v4 |
| 354 | - name: Setup Buildx |
| 355 | id: prepare |
| 356 | uses: docker/setup-buildx-action@v4 |
| 357 | - name: Registry Login |
| 358 | id: login |
| 359 | if: github.repository == 'netdata/netdata' |
| 360 | uses: docker/login-action@v4 |
| 361 | with: |
| 362 | username: ${{ secrets.DOCKER_HUB_USERNAME }} |
| 363 | password: ${{ secrets.DOCKER_HUB_PASSWORD }} |
| 364 | - name: Build Image |
| 365 | id: build |
| 366 | uses: docker/build-push-action@v7 |
| 367 | with: |
| 368 | platforms: ${{ matrix.platform }} |
| 369 | cache-from: type=local,src=/tmp/build-cache |
| 370 | outputs: type=image,name=netdata/netdata,push-by-digest=true,name-canonical=true,push=true |
| 371 | build-args: | |
| 372 | OFFICIAL_IMAGE=${{ env.OFFICIAL_IMAGE }} |
| 373 | BUILD_ARCH=${{ matrix.arch }} |
| 374 | BUILD_VERSION=${{ github.event.inputs.version }} |
| 375 | BUILD_DATE=${{ github.event.repository.updated_at }} |
| 376 | - name: Export Digest |
| 377 | id: export-digest |
| 378 | if: github.repository == 'netdata/netdata' |
| 379 | run: | |
| 380 | mkdir -p /tmp/digests |
| 381 | digest="${{ steps.build.outputs.digest }}" |
| 382 | touch "/tmp/digests/${digest#sha256:}" |
| 383 | - name: Upload digest |
| 384 | id: upload-digest |
| 385 | if: github.repository == 'netdata/netdata' |
| 386 | uses: actions/upload-artifact@v7.0.1 |
| 387 | with: |
| 388 | name: docker-digests-${{ steps.artifact-name.outputs.platform }} |
| 389 | path: /tmp/digests/* |
| 390 | if-no-files-found: error |
| 391 | retention-days: 1 |
| 392 | - name: Failure Notification |
| 393 | uses: rtCamp/action-slack-notify@v2 |
| 394 | env: |
| 395 | SLACK_COLOR: 'danger' |
| 396 | SLACK_FOOTER: '' |
| 397 | SLACK_ICON_EMOJI: ':github-actions:' |
| 398 | SLACK_TITLE: 'Docker Hub upload failed:' |
| 399 | SLACK_USERNAME: 'GitHub Actions' |
| 400 | SLACK_MESSAGE: |- |
| 401 | ${{ github.repository }}: Creating or uploading Docker image for ${{ matrix.platform }} on Docker Hub failed. |
| 402 | Checkout: ${{ steps.checkout.outcome }} |
| 403 | Determine artifact name: ${{ steps.artifact-name.outcome }} |
| 404 | Fetch build cache: ${{ steps.fetch-cache.outcome }} |
| 405 | Setup environment: ${{ steps.env.outcome }} |
| 406 | Setup QEMU: ${{ steps.qemu.outcome }} |
| 407 | Setup buildx: ${{ steps.prepare.outcome }} |
| 408 | Login to registry: ${{ steps.login.outcome }} |
| 409 | Build image: ${{ steps.build.outcome }} |
| 410 | Export digest: ${{ steps.export-digest.outcome }} |
| 411 | Upload digest: ${{ steps.upload-digest.outcome }} |
| 412 | SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }} |
| 413 | if: >- |
| 414 | ${{ |
| 415 | failure() |
| 416 | && github.repository == 'netdata/netdata' |
| 417 | }} |
| 418 | |
| 419 | publish-docker-hub: |
| 420 | name: Consolidate and tag images for DockerHub |
| 421 | if: github.event_name == 'workflow_dispatch' |
| 422 | needs: |
| 423 | - build-images-docker-hub |
| 424 | - gen-tags |
| 425 | runs-on: ubuntu-latest |
| 426 | steps: |
| 427 | - name: Checkout |
| 428 | id: checkout |
| 429 | uses: actions/checkout@v6 |
| 430 | - name: Download digests |
| 431 | id: fetch-digests |
| 432 | uses: actions/download-artifact@v8 |
| 433 | with: |
| 434 | path: /tmp/digests |
| 435 | pattern: docker-digests-* |
| 436 | merge-multiple: true |
| 437 | - name: Setup Buildx |
| 438 | id: prepare |
| 439 | uses: docker/setup-buildx-action@v4 |
| 440 | - name: Registry Login |
| 441 | id: login |
| 442 | if: github.repository == 'netdata/netdata' |
| 443 | uses: docker/login-action@v4 |
| 444 | with: |
| 445 | username: ${{ secrets.DOCKER_HUB_USERNAME }} |
| 446 | password: ${{ secrets.DOCKER_HUB_PASSWORD }} |
| 447 | - name: Create and Push Manifest |
| 448 | id: manifest |
| 449 | if: github.repository == 'netdata/netdata' |
| 450 | run: docker buildx imagetools create $(.github/scripts/gen-docker-imagetool-args.py /tmp/digests '' "${{ needs.gen-tags.outputs.tags }}") |
| 451 | - name: Rotate Old Image Tags |
| 452 | id: rotate |
| 453 | if: github.repository == 'netdata/netdata' && needs.gen-tags.outputs.nightly == '1' |
| 454 | run: .github/scripts/rotate-docker-tags.sh ${{ needs.gen-tags.outputs.docker_repo }} ${{ needs.gen-tags.outputs.nightly_tag }} ${NIGHTLY_COUNT} |
| 455 | - name: Failure Notification |
| 456 | uses: rtCamp/action-slack-notify@v2 |
| 457 | env: |
| 458 | SLACK_COLOR: 'danger' |
| 459 | SLACK_FOOTER: '' |
| 460 | SLACK_ICON_EMOJI: ':github-actions:' |
| 461 | SLACK_TITLE: 'Publishing Docker images to Docker Hub failed:' |
| 462 | SLACK_USERNAME: 'GitHub Actions' |
| 463 | SLACK_MESSAGE: |- |
| 464 | ${{ github.repository }}: Publishing Docker images to Docker Hub failed. |
| 465 | Checkout: ${{ steps.checkout.outcome }} |
| 466 | Download digests: ${{ steps.fetch-digests.outcome }} |
| 467 | Setup buildx: ${{ steps.prepare.outcome }} |
| 468 | Login to registry: ${{ steps.login.outcome }} |
| 469 | Create and push manifest: ${{ steps.manifest.outcome }} |
| 470 | Rotate old image tags: ${{ steps.rotate.outcome }} |
| 471 | SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }} |
| 472 | if: >- |
| 473 | ${{ |
| 474 | failure() |
| 475 | && github.repository == 'netdata/netdata' |
| 476 | }} |
| 477 | |
| 478 | build-images-quay: |
| 479 | name: Push Images to Quay.io |
| 480 | if: github.event_name == 'workflow_dispatch' |
| 481 | needs: |
| 482 | - build-images |
| 483 | - gen-tags |
| 484 | - matrix |
| 485 | strategy: |
| 486 | matrix: ${{ fromJson(needs.matrix.outputs.matrix) }} |
| 487 | runs-on: ${{ matrix.runner }} |
| 488 | steps: |
| 489 | - name: Checkout |
| 490 | id: checkout |
| 491 | uses: actions/checkout@v6 |
| 492 | with: |
| 493 | fetch-depth: 0 |
| 494 | submodules: recursive |
| 495 | - name: Generate Artifact Name |
| 496 | id: artifact-name |
| 497 | run: echo "platform=$(echo ${{ matrix.platform }} | tr '/' '-' | cut -f 2- -d '-')" >> "${GITHUB_OUTPUT}" |
| 498 | - name: Download Cache |
| 499 | id: fetch-cache |
| 500 | uses: actions/download-artifact@v8 |
| 501 | with: |
| 502 | name: cache-${{ steps.artifact-name.outputs.platform }} |
| 503 | path: /tmp/build-cache |
| 504 | - name: Mark image as official |
| 505 | id: env |
| 506 | if: github.repository == 'netdata/netdata' |
| 507 | run: echo "OFFICIAL_IMAGE=true" >> "${GITHUB_ENV}" |
| 508 | - name: Setup QEMU |
| 509 | id: qemu |
| 510 | if: matrix.qemu |
| 511 | uses: docker/setup-qemu-action@v4 |
| 512 | - name: Setup Buildx |
| 513 | id: prepare |
| 514 | uses: docker/setup-buildx-action@v4 |
| 515 | - name: Registry Login |
| 516 | id: login |
| 517 | if: github.repository == 'netdata/netdata' |
| 518 | uses: docker/login-action@v4 |
| 519 | with: |
| 520 | registry: quay.io |
| 521 | username: ${{ secrets.NETDATABOT_QUAY_USERNAME }} |
| 522 | password: ${{ secrets.NETDATABOT_QUAY_TOKEN }} |
| 523 | - name: Build Image |
| 524 | id: build |
| 525 | uses: docker/build-push-action@v7 |
| 526 | with: |
| 527 | platforms: ${{ matrix.platform }} |
| 528 | cache-from: type=local,src=/tmp/build-cache |
| 529 | build-args: | |
| 530 | OFFICIAL_IMAGE=${{ env.OFFICIAL_IMAGE }} |
| 531 | BUILD_ARCH=${{ matrix.arch }} |
| 532 | BUILD_VERSION=${{ github.event.inputs.version }} |
| 533 | BUILD_DATE=${{ github.event.repository.updated_at }} |
| 534 | outputs: type=image,name=quay.io/netdata/netdata,push-by-digest=true,name-canonical=true,push=true |
| 535 | - name: Export Digest |
| 536 | id: export-digest |
| 537 | if: github.repository == 'netdata/netdata' |
| 538 | run: | |
| 539 | mkdir -p /tmp/digests |
| 540 | digest="${{ steps.build.outputs.digest }}" |
| 541 | touch "/tmp/digests/${digest#sha256:}" |
| 542 | - name: Upload digest |
| 543 | id: upload-digest |
| 544 | if: github.repository == 'netdata/netdata' |
| 545 | uses: actions/upload-artifact@v7.0.1 |
| 546 | with: |
| 547 | name: quay-digests-${{ steps.artifact-name.outputs.platform }} |
| 548 | path: /tmp/digests/* |
| 549 | if-no-files-found: error |
| 550 | retention-days: 1 |
| 551 | - name: Failure Notification |
| 552 | uses: rtCamp/action-slack-notify@v2 |
| 553 | env: |
| 554 | SLACK_COLOR: 'danger' |
| 555 | SLACK_FOOTER: '' |
| 556 | SLACK_ICON_EMOJI: ':github-actions:' |
| 557 | SLACK_TITLE: 'Quay.io upload failed:' |
| 558 | SLACK_USERNAME: 'GitHub Actions' |
| 559 | SLACK_MESSAGE: |- |
| 560 | ${{ github.repository }}: Creating or uploading Docker image for ${{ matrix.platform }} on Quay.io failed. |
| 561 | Checkout: ${{ steps.checkout.outcome }} |
| 562 | Determine artifact name: ${{ steps.artifact-name.outcome }} |
| 563 | Fetch build cache: ${{ steps.fetch-cache.outcome }} |
| 564 | Setup environment: ${{ steps.env.outcome }} |
| 565 | Setup QEMU: ${{ steps.qemu.outcome }} |
| 566 | Setup buildx: ${{ steps.prepare.outcome }} |
| 567 | Login to registry: ${{ steps.login.outcome }} |
| 568 | Build image: ${{ steps.build.outcome }} |
| 569 | Export digest: ${{ steps.export-digest.outcome }} |
| 570 | Upload digest: ${{ steps.upload-digest.outcome }} |
| 571 | SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }} |
| 572 | if: >- |
| 573 | ${{ |
| 574 | failure() |
| 575 | && github.repository == 'netdata/netdata' |
| 576 | }} |
| 577 | |
| 578 | publish-quay: |
| 579 | name: Consolidate and tag images for Quay.io |
| 580 | if: github.event_name == 'workflow_dispatch' |
| 581 | needs: |
| 582 | - build-images-quay |
| 583 | - gen-tags |
| 584 | runs-on: ubuntu-latest |
| 585 | steps: |
| 586 | - name: Checkout |
| 587 | id: checkout |
| 588 | uses: actions/checkout@v6 |
| 589 | - name: Download digests |
| 590 | id: fetch-digests |
| 591 | uses: actions/download-artifact@v8 |
| 592 | with: |
| 593 | path: /tmp/digests |
| 594 | pattern: quay-digests-* |
| 595 | merge-multiple: true |
| 596 | - name: Setup Buildx |
| 597 | id: prepare |
| 598 | uses: docker/setup-buildx-action@v4 |
| 599 | - name: Registry Login |
| 600 | id: login |
| 601 | if: github.repository == 'netdata/netdata' |
| 602 | uses: docker/login-action@v4 |
| 603 | with: |
| 604 | registry: quay.io |
| 605 | username: ${{ secrets.NETDATABOT_QUAY_USERNAME }} |
| 606 | password: ${{ secrets.NETDATABOT_QUAY_TOKEN }} |
| 607 | - name: Create and Push Manifest |
| 608 | id: manifest |
| 609 | if: github.repository == 'netdata/netdata' |
| 610 | run: docker buildx imagetools create $(.github/scripts/gen-docker-imagetool-args.py /tmp/digests 'quay.io' "${{ needs.gen-tags.outputs.tags }}") |
| 611 | - name: Rotate Old Image Tags |
| 612 | id: rotate |
| 613 | if: github.repository == 'netdata/netdata' && needs.gen-tags.outputs.nightly == '1' |
| 614 | run: .github/scripts/rotate-docker-tags.sh ${{ needs.gen-tags.outputs.quay_repo }} ${{ needs.gen-tags.outputs.nightly_tag }} ${NIGHTLY_COUNT} |
| 615 | - name: Failure Notification |
| 616 | uses: rtCamp/action-slack-notify@v2 |
| 617 | env: |
| 618 | SLACK_COLOR: 'danger' |
| 619 | SLACK_FOOTER: '' |
| 620 | SLACK_ICON_EMOJI: ':github-actions:' |
| 621 | SLACK_TITLE: 'Publishing Docker images on Quay.io failed:' |
| 622 | SLACK_USERNAME: 'GitHub Actions' |
| 623 | SLACK_MESSAGE: |- |
| 624 | ${{ github.repository }}: Publishing Docker images on Quay.io failed. |
| 625 | Checkout: ${{ steps.checkout.outcome }} |
| 626 | Download digests: ${{ steps.fetch-digests.outcome }} |
| 627 | Setup buildx: ${{ steps.prepare.outcome }} |
| 628 | Login to registry: ${{ steps.login.outcome }} |
| 629 | Create and push manifest: ${{ steps.manifest.outcome }} |
| 630 | Rotate old image tags: ${{ steps.rotate.outcome }} |
| 631 | SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }} |
| 632 | if: >- |
| 633 | ${{ |
| 634 | failure() |
| 635 | && github.repository == 'netdata/netdata' |
| 636 | }} |
| 637 | |
| 638 | build-images-ghcr: |
| 639 | name: Push Images to GHCR |
| 640 | if: github.event_name == 'workflow_dispatch' |
| 641 | needs: |
| 642 | - build-images |
| 643 | - gen-tags |
| 644 | - matrix |
| 645 | strategy: |
| 646 | matrix: ${{ fromJson(needs.matrix.outputs.matrix) }} |
| 647 | runs-on: ${{ matrix.runner }} |
| 648 | steps: |
| 649 | - name: Checkout |
| 650 | id: checkout |
| 651 | uses: actions/checkout@v6 |
| 652 | with: |
| 653 | fetch-depth: 0 |
| 654 | submodules: recursive |
| 655 | - name: Generate Artifact Name |
| 656 | id: artifact-name |
| 657 | run: echo "platform=$(echo ${{ matrix.platform }} | tr '/' '-' | cut -f 2- -d '-')" >> "${GITHUB_OUTPUT}" |
| 658 | - name: Download Cache |
| 659 | id: fetch-cache |
| 660 | uses: actions/download-artifact@v8 |
| 661 | with: |
| 662 | name: cache-${{ steps.artifact-name.outputs.platform }} |
| 663 | path: /tmp/build-cache |
| 664 | - name: Mark image as official |
| 665 | id: env |
| 666 | if: github.repository == 'netdata/netdata' |
| 667 | run: echo "OFFICIAL_IMAGE=true" >> "${GITHUB_ENV}" |
| 668 | - name: Setup QEMU |
| 669 | id: qemu |
| 670 | if: matrix.qemu |
| 671 | uses: docker/setup-qemu-action@v4 |
| 672 | - name: Setup Buildx |
| 673 | id: prepare |
| 674 | uses: docker/setup-buildx-action@v4 |
| 675 | - name: Registry Login |
| 676 | id: login |
| 677 | if: github.repository == 'netdata/netdata' |
| 678 | uses: docker/login-action@v4 |
| 679 | with: |
| 680 | registry: ghcr.io |
| 681 | username: ${{ github.repository_owner }} |
| 682 | password: ${{ secrets.GITHUB_TOKEN }} |
| 683 | - name: Build Image |
| 684 | id: build |
| 685 | uses: docker/build-push-action@v7 |
| 686 | with: |
| 687 | platforms: ${{ matrix.platform }} |
| 688 | cache-from: type=local,src=/tmp/build-cache |
| 689 | build-args: | |
| 690 | OFFICIAL_IMAGE=${{ env.OFFICIAL_IMAGE }} |
| 691 | BUILD_ARCH=${{ matrix.arch }} |
| 692 | BUILD_VERSION=${{ github.event.inputs.version }} |
| 693 | BUILD_DATE=${{ github.event.repository.updated_at }} |
| 694 | outputs: type=image,name=ghcr.io/netdata/netdata,push-by-digest=true,name-canonical=true,push=true |
| 695 | - name: Export Digest |
| 696 | id: export-digest |
| 697 | if: github.repository == 'netdata/netdata' |
| 698 | run: | |
| 699 | mkdir -p /tmp/digests |
| 700 | digest="${{ steps.build.outputs.digest }}" |
| 701 | touch "/tmp/digests/${digest#sha256:}" |
| 702 | - name: Upload digest |
| 703 | id: upload-digest |
| 704 | if: github.repository == 'netdata/netdata' |
| 705 | uses: actions/upload-artifact@v7.0.1 |
| 706 | with: |
| 707 | name: ghcr-digests-${{ steps.artifact-name.outputs.platform }} |
| 708 | path: /tmp/digests/* |
| 709 | if-no-files-found: error |
| 710 | retention-days: 1 |
| 711 | - name: Failure Notification |
| 712 | uses: rtCamp/action-slack-notify@v2 |
| 713 | env: |
| 714 | SLACK_COLOR: 'danger' |
| 715 | SLACK_FOOTER: '' |
| 716 | SLACK_ICON_EMOJI: ':github-actions:' |
| 717 | SLACK_TITLE: 'GHCR upload failed:' |
| 718 | SLACK_USERNAME: 'GitHub Actions' |
| 719 | SLACK_MESSAGE: |- |
| 720 | ${{ github.repository }}: Creating or uploading Docker image for ${{ matrix.platform }} on GHCR failed. |
| 721 | Checkout: ${{ steps.checkout.outcome }} |
| 722 | Determine artifact name: ${{ steps.artifact-name.outcome }} |
| 723 | Fetch build cache: ${{ steps.fetch-cache.outcome }} |
| 724 | Setup environment: ${{ steps.env.outcome }} |
| 725 | Setup QEMU: ${{ steps.qemu.outcome }} |
| 726 | Setup buildx: ${{ steps.prepare.outcome }} |
| 727 | Login to registry: ${{ steps.login.outcome }} |
| 728 | Build image: ${{ steps.build.outcome }} |
| 729 | Export digest: ${{ steps.export-digest.outcome }} |
| 730 | Upload digest: ${{ steps.upload-digest.outcome }} |
| 731 | SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }} |
| 732 | if: >- |
| 733 | ${{ |
| 734 | failure() |
| 735 | && github.repository == 'netdata/netdata' |
| 736 | }} |
| 737 | |
| 738 | publish-ghcr: |
| 739 | name: Consolidate and tag images for GHCR |
| 740 | if: github.event_name == 'workflow_dispatch' |
| 741 | needs: |
| 742 | - build-images-ghcr |
| 743 | - gen-tags |
| 744 | runs-on: ubuntu-latest |
| 745 | steps: |
| 746 | - name: Checkout |
| 747 | id: checkout |
| 748 | uses: actions/checkout@v6 |
| 749 | - name: Download digests |
| 750 | id: fetch-digests |
| 751 | uses: actions/download-artifact@v8 |
| 752 | with: |
| 753 | path: /tmp/digests |
| 754 | pattern: ghcr-digests-* |
| 755 | merge-multiple: true |
| 756 | - name: Setup Buildx |
| 757 | id: prepare |
| 758 | uses: docker/setup-buildx-action@v4 |
| 759 | - name: Registry Login |
| 760 | id: login |
| 761 | if: github.repository == 'netdata/netdata' |
| 762 | uses: docker/login-action@v4 |
| 763 | with: |
| 764 | registry: ghcr.io |
| 765 | username: ${{ github.repository_owner }} |
| 766 | password: ${{ secrets.GITHUB_TOKEN }} |
| 767 | - name: Create and Push Manifest |
| 768 | id: manifest |
| 769 | if: github.repository == 'netdata/netdata' |
| 770 | run: docker buildx imagetools create $(.github/scripts/gen-docker-imagetool-args.py /tmp/digests 'ghcr.io' "${{ needs.gen-tags.outputs.tags }}") |
| 771 | - name: Rotate Old Image Tags |
| 772 | id: rotate |
| 773 | if: github.repository == 'netdata/netdata' && needs.gen-tags.outputs.nightly == '1' |
| 774 | run: .github/scripts/rotate-docker-tags.sh ${{ needs.gen-tags.outputs.ghcr_repo }} ${{ needs.gen-tags.outputs.nightly_tag }} ${NIGHTLY_COUNT} |
| 775 | - name: Failure Notification |
| 776 | uses: rtCamp/action-slack-notify@v2 |
| 777 | env: |
| 778 | SLACK_COLOR: 'danger' |
| 779 | SLACK_FOOTER: '' |
| 780 | SLACK_ICON_EMOJI: ':github-actions:' |
| 781 | SLACK_TITLE: 'Publishing Docker images on GHCR failed:' |
| 782 | SLACK_USERNAME: 'GitHub Actions' |
| 783 | SLACK_MESSAGE: |- |
| 784 | ${{ github.repository }}: Publishing Docker images on GHCR failed. |
| 785 | Checkout: ${{ steps.checkout.outcome }} |
| 786 | Download digests: ${{ steps.fetch-digests.outcome }} |
| 787 | Setup buildx: ${{ steps.prepare.outcome }} |
| 788 | Login to registry: ${{ steps.login.outcome }} |
| 789 | Create and push manifest: ${{ steps.manifest.outcome }} |
| 790 | Rotate old image tags: ${{ steps.rotate.outcome }} |
| 791 | SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }} |
| 792 | if: >- |
| 793 | ${{ |
| 794 | failure() |
| 795 | && github.repository == 'netdata/netdata' |
| 796 | }} |
| 797 | |
| 798 | trigger-subsequent-workflows: |
| 799 | if: github.event_name == 'workflow_dispatch' |
| 800 | name: Trigger subsquent workflows for newly added versions |
| 801 | needs: |
| 802 | - publish-docker-hub |
| 803 | - gen-tags |
| 804 | runs-on: ubuntu-latest |
| 805 | steps: |
| 806 | - name: Checkout |
| 807 | id: checkout |
| 808 | uses: actions/checkout@v6 |
| 809 | with: |
| 810 | submodules: recursive |
| 811 | - name: Trigger Helmchart PR |
| 812 | if: github.event_name == 'workflow_dispatch' && github.event.inputs.version != 'nightly' && github.repository == 'netdata/netdata' |
| 813 | id: trigger-helmchart |
| 814 | uses: benc-uk/workflow-dispatch@v1 |
| 815 | with: |
| 816 | token: ${{ secrets.NETDATABOT_GITHUB_TOKEN }} |
| 817 | repo: netdata/helmchart |
| 818 | workflow: Agent Version PR |
| 819 | ref: refs/heads/master |
| 820 | inputs: '{"agent_version": "v${{ inputs.version }}"}' |
| 821 | - name: Trigger MSI build |
| 822 | if: github.event_name == 'workflow_dispatch' && github.event.inputs.version != 'nightly' && github.repository == 'netdata/netdata' |
| 823 | id: trigger-msi |
| 824 | uses: benc-uk/workflow-dispatch@v1 |
| 825 | with: |
| 826 | token: ${{ secrets.NETDATABOT_GITHUB_TOKEN }} |
| 827 | repo: netdata/msi-installer |
| 828 | workflow: Build |
| 829 | ref: refs/heads/master |
| 830 | inputs: '{"tag": "stable", "pwd": "${{ secrets.MSI_CODE_SIGNING_PASSWORD }}"}' |
| 831 | - name: Failure Notification |
| 832 | uses: rtCamp/action-slack-notify@v2 |
| 833 | env: |
| 834 | SLACK_COLOR: 'danger' |
| 835 | SLACK_FOOTER: '' |
| 836 | SLACK_ICON_EMOJI: ':github-actions:' |
| 837 | SLACK_TITLE: ':' |
| 838 | SLACK_USERNAME: 'GitHub Actions' |
| 839 | SLACK_MESSAGE: |- |
| 840 | ${{ github.repository }}: Version cascade failed |
| 841 | Checkout: ${{ steps.checkout.outcome }} |
| 842 | Trigger Helmchart PR: ${{ steps.trigger-helmchart.outcome }} |
| 843 | Trigger MSI build: ${{ steps.trigger-msi.outcome }} |
| 844 | SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }} |
| 845 | if: >- |
| 846 | ${{ |
| 847 | failure() |
| 848 | && github.event_name != 'pull_request' |
| 849 | && startsWith(github.ref, 'refs/heads/master') |
| 850 | && github.repository == 'netdata/netdata' |
| 851 | }} |