Commit 1c709926 authored by Pierre Smeyers's avatar Pierre Smeyers
Browse files

feat: add parallel:matrix support

parent 30791333
Loading
Loading
Loading
Loading
+50 −0
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ The CNB template uses some global configuration used throughout all jobs.
| `builder-image` / `CNB_BUILDER_IMAGE` | The CNB builder image used to build your application image<br/>_depending on your needs, [choose the most appropriate one](https://paketo.io/docs/concepts/builders/#what-paketo-builders-are-available)_ | `docker.io/paketobuildpacks/builder-jammy-base:latest` <br/>[![Trivy Badge](https://to-be-continuous.gitlab.io/doc/secu/trivy-badge-CNB_BUILDER_IMAGE.svg)](https://to-be-continuous.gitlab.io/doc/secu/trivy-CNB_BUILDER_IMAGE) |
| `platform-api` / `CNB_PLATFORM_API` | The CNB [platform API version](https://github.com/buildpacks/spec/blob/main/platform.md#platform-api-version) | `0.14` |
| `source-date-epoch-enabled` / `CNB_SOURCE_DATE_EPOCH_ENABLED` | Enable setting [`SOURCE_DATE_EPOCH` to configure image create time](https://github.com/buildpacks/rfcs/blob/main/text/0103-source-date-epoch.md) based on Git commit date. | `false` |
| `artifacts-namespace` / `CNB_ARTIFACTS_NAMESPACE` | Output artifacts namespace _(only required when deploying [multiple environments](#multiple-environments-support))_ | _none_ |

### Available Builders

@@ -129,6 +130,35 @@ If you use **different registries** for snapshot and release images, you shall u
| :lock: `CNB_REGISTRY_RELEASE_USER`    | container registry username for release image registry |
| :lock: `CNB_REGISTRY_RELEASE_PASSWORD`| container registry password for release image registry |

### Multiple images build

The CNB template allows building multiple images in parallel (for instance with multiple separate application source code base directories in your repository).

This feature can be enabled using the [parallel matrix jobs](https://docs.gitlab.com/ee/ci/yaml/#parallelmatrix)
pattern at the `.cnb-base` job level. 
:information: Output variables namespacing can be ensured by using the `CNB_ARTIFACTS_NAMESPACE` variable.

Here is the example of the `.gitlab-ci.yml` file for a project building 2 application images:

```yaml
.cnb-base:
  parallel:
    matrix:
      - CNB_ARTIFACTS_NAMESPACE: "app1"
        CNB_APP_DIR: "src/app1"
        CNB_SNAPSHOT_IMAGE: "$CI_REGISTRY_IMAGE/app1/snapshot:$CI_COMMIT_REF_SLUG"
        CNB_RELEASE_IMAGE: "$CI_REGISTRY_IMAGE/app1:$CI_COMMIT_REF_NAME"
      - CNB_ARTIFACTS_NAMESPACE: "app2"
        CNB_APP_DIR: "src/app2"
        CNB_SNAPSHOT_IMAGE: "$CI_REGISTRY_IMAGE/app2/snapshot:$CI_COMMIT_REF_SLUG"
        CNB_RELEASE_IMAGE: "$CI_REGISTRY_IMAGE/app2:$CI_COMMIT_REF_NAME"
```

The above configuration will instantiate the CNB pipeline twice, one for each application with all required jobs.

> [!tip]
> Setting the `CNB_ARTIFACTS_NAMESPACE` variable is only necessary if you need to namespace the build job output variables.

### Secrets management

Here are some advices about your **secrets** (variables marked with a :lock:):
@@ -193,6 +223,16 @@ This job produces _output variables_ that are propagated to downstream jobs (usi

They may be freely used in downstream jobs (for instance to deploy the upstream built image, whatever the branch or tag).

> [!important]
> If [multiple images build](#multiple-images-build) is configured and `CNB_ARTIFACTS_NAMESPACE` is set, the output variables are namespaced with a 
> sluggified value of the `CNB_ARTIFACTS_NAMESPACE` variable (stripped of punctuation characters and converted to lowercase):
> 
> * `cnb_<namespace_slug>_image`: snapshot image name **with tag**,
> * `cnb_<namespace_slug>_image_digest`: snapshot image name **with digest** (no tag),
> * `cnb_<namespace_slug>_repository`: snapshot image **bare repository** (no tag nor digest),
> * `cnb_<namespace_slug>_tag`: snapshot image tag,
> * `cnb_<namespace_slug>_digest`: snapshot image digest.

#### User-Provided variables support

> [User-Provided variables](https://github.com/buildpacks/spec/blob/main/platform.md#user-provided-variables) must be prefixed with `CNB_X_`
@@ -267,6 +307,16 @@ This job produces _output variables_ that are propagated to downstream jobs (usi

They may be freely used in downstream jobs (for instance to deploy the upstream built image, whatever the branch or tag).

> [!important]
> If [multiple images build](#multiple-images-build) is configured and `CNB_ARTIFACTS_NAMESPACE` is set, the output variables are namespaced with a 
> sluggified value of the `CNB_ARTIFACTS_NAMESPACE` variable (stripped of punctuation characters and converted to lowercase):
> 
> * `cnb_<namespace_slug>_image`: release image name **with tag**,
> * `cnb_<namespace_slug>_image_digest`: release image name **with digest** (no tag),
> * `cnb_<namespace_slug>_repository`: release image **bare repository** (no tag nor digest),
> * `cnb_<namespace_slug>_tag`: release image tag,
> * `cnb_<namespace_slug>_digest`: release image digest.

#### Using extra tags

When publishing the _release_ image, the Docker template might publish it again with additional tags (aliases):
+5 −0
Original line number Diff line number Diff line
@@ -54,6 +54,11 @@
      "name": "CNB_RELEASE_EXTRA_TAGS",
      "description": "Defines extra tags to publish the _release_ image\n\nSupports capturing group references from `$CNB_RELEASE_EXTRA_TAGS_PATTERN` (ex: `latest \\g<major>.\\g<minor> \\g<major>`)",
      "advanced": true
    },
    {
      "name": "CNB_ARTIFACTS_NAMESPACE",
      "description": "Output artifacts namespace _(only required when building multiple images)_",
      "advanced": true
    }
  ],
  "features": [
+26 −22
Original line number Diff line number Diff line
@@ -41,6 +41,9 @@ spec:
    release-image:
      description: CNB release image
      default: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME
    artifacts-namespace:
      description: Output artifacts namespace _(only required when building multiple images)_
      default: ''
    release-extra-tags-pattern:
      description: |-
        Defines the image tag pattern that `$CNB_RELEASE_IMAGE` should match to push extra tags (supports capturing groups)
@@ -157,6 +160,7 @@ variables:
  CNB_SRC_APP_DIR: $[[ inputs.src-app-dir ]]
  # default final image hierarchy root dir
  CNB_APP_DIR: $[[ inputs.app-dir ]]
  CNB_ARTIFACTS_NAMESPACE: $[[ inputs.artifacts-namespace ]]

  # default: one-click publish
  CNB_PROD_PUBLISH_STRATEGY: $[[ inputs.prod-publish-strategy ]]
@@ -696,6 +700,24 @@ stages:
    rm -f "${FIND_PATTERNS_FILE}"
  }

  function create_dotenv_file() {
    cnb_digest=$1
    cnb_image=${2:-$CNB_SNAPSHOT_IMAGE}
    cnb_repository=${cnb_image%:*}
    cnb_tag=${cnb_image##*:}
    ans_slug=$(echo "$CNB_ARTIFACTS_NAMESPACE" | tr -d '[:punct:]' | tr '[:upper:]' '[:lower:]')
    var_prefix="${ans_slug:+${ans_slug}_}"
    dotenvfile="cnb.env${ans_slug:+.${ans_slug}}"
    {
      echo "cnb_${var_prefix}image=$cnb_image"
      echo "cnb_${var_prefix}image_digest=$cnb_repository@$cnb_digest"
      echo "cnb_${var_prefix}repository=$cnb_repository"
      echo "cnb_${var_prefix}tag=$cnb_tag"
      echo "cnb_${var_prefix}digest=$cnb_digest"
    } > "$dotenvfile"
    chmod 644 "$dotenvfile"
  }

  function publish_extra_tags() {
    if [[ -z "$CNB_RELEASE_EXTRA_TAGS" ]]
    then
@@ -769,19 +791,11 @@ cnb-build:
    - /cnb/lifecycle/creator -report cnb-report.toml "$CNB_SNAPSHOT_IMAGE"
    # create output dotenv file
    - cnb_digest=$(grep -e " *digest *=" cnb-report.toml | cut -d'"' -f2)
    - |
      {
        echo "cnb_image=$CNB_SNAPSHOT_IMAGE"
        echo "cnb_image_digest=$cnb_repository@$cnb_digest"
        echo "cnb_repository=$cnb_repository"
        echo "cnb_tag=$cnb_tag"
        echo "cnb_digest=$cnb_digest"
      } > cnb.env
      chmod 644 cnb.env
    - create_dotenv_file "$cnb_digest"
  artifacts:
    reports:
      dotenv:
        - cnb.env
        - cnb.env*

# Security audit with trivy
cnb-trivy:
@@ -848,23 +862,13 @@ cnb-publish:
      fi
      skopeo copy --src-authfile ~/.docker/config.json --dest-authfile ~/.docker/release-config.json ${CNB_PUBLISH_ARGS} docker://$CNB_SNAPSHOT_IMAGE docker://$CNB_RELEASE_IMAGE
      log_info "Well done your image is published and can be downloaded by doing: docker pull $CNB_RELEASE_IMAGE"
    - cnb_repository=${CNB_RELEASE_IMAGE%:*}
    - cnb_tag=${CNB_RELEASE_IMAGE##*:}
    - cnb_digest=$(skopeo inspect --authfile ~/.docker/release-config.json --format='{{ .Digest }}' "docker://$CNB_RELEASE_IMAGE")
    - |
      {
        echo "cnb_image=$CNB_RELEASE_IMAGE"
        echo "cnb_image_digest=$cnb_repository@$cnb_digest"
        echo "cnb_repository=$cnb_repository"
        echo "cnb_tag=$cnb_tag"
        echo "cnb_digest=$cnb_digest"
      } > cnb.env
      chmod 644 cnb.env
    - create_dotenv_file "$cnb_digest" "$CNB_RELEASE_IMAGE"
    - publish_extra_tags
  artifacts:
    reports:
      dotenv:
        - cnb.env
        - cnb.env*
  rules:
    # on tag: always
    - if: $CI_COMMIT_TAG