From b3b3d27edd00525afe57627a871db661f2201f9c Mon Sep 17 00:00:00 2001
From: Pierre Smeyers <pierre.smeyers@gmail.com>
Date: Sat, 25 Nov 2023 15:09:51 +0000
Subject: [PATCH] feat: initial template

---
 .gitignore                                 |   1 +
 .gitlab-ci.yml                             |  29 +++
 .gitlab/issue_templates/feature_request.md |   2 +-
 .releaserc.yml                             |  22 ++
 CONTRIBUTE.md => CONTRIBUTING.md           |   2 +
 README.md                                  |  39 ++-
 Renovate.r2.yml                            |  13 +
 SECURITY.md                                |  14 ++
 bumpversion.sh                             |  41 ++++
 kicker.json                                |  23 ++
 logo.png                                   | Bin 11231 -> 5364 bytes
 post-release.sh                            |  35 +++
 templates/gitlab-ci-renovate.yml           | 265 +++++++++++++++++++++
 13 files changed, 481 insertions(+), 5 deletions(-)
 create mode 100644 .gitignore
 create mode 100644 .gitlab-ci.yml
 create mode 100644 .releaserc.yml
 rename CONTRIBUTE.md => CONTRIBUTING.md (97%)
 create mode 100644 Renovate.r2.yml
 create mode 100644 SECURITY.md
 create mode 100755 bumpversion.sh
 create mode 100644 kicker.json
 create mode 100755 post-release.sh
 create mode 100644 templates/gitlab-ci-renovate.yml

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..485dee6
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+.idea
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000..f40668c
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,29 @@
+include:
+  - project: 'to-be-continuous/tools/gitlab-ci'
+    ref: 'master'
+    file: '/templates/extract.yml'
+  - project: 'to-be-continuous/tools/gitlab-ci'
+    ref: 'master'
+    file: '/templates/validation.yml'
+  - project: 'to-be-continuous/kicker'
+    ref: 'master'
+    file: '/templates/validation.yml'
+  - project: 'to-be-continuous/bash'
+    ref: '3.2'
+    file: 'templates/gitlab-ci-bash.yml'
+  - project: 'to-be-continuous/semantic-release'
+    ref: '3.6'
+    file: '/templates/gitlab-ci-semrel.yml'
+
+stages:
+  - build
+  - publish
+
+variables:
+  GITLAB_CI_FILES: "templates/gitlab-ci-renovate.yml"
+  BASH_SHELLCHECK_FILES: "*.sh"
+
+semantic-release:
+  rules:
+    # on production branch(es): auto if SEMREL_AUTO_RELEASE_ENABLED
+    - if: '$TMPL_RELEASE_ENABLED == "true" && $CI_COMMIT_REF_NAME =~ $PROD_REF'
diff --git a/.gitlab/issue_templates/feature_request.md b/.gitlab/issue_templates/feature_request.md
index b751851..666c5fb 100644
--- a/.gitlab/issue_templates/feature_request.md
+++ b/.gitlab/issue_templates/feature_request.md
@@ -5,7 +5,7 @@
 ## Implementation ideas
 
 (If you have any implementation ideas, they can go here.)
-(Any design change proposal could be also discussed on the _to be continuous_ Google Group: https://groups.google.com/g/tbc-dev.)
+(Any design change proposal could be also discussed on the _to be continuous_ Discord server.)
 
 
 /label ~"kind/enhancement" ~"status/needs-investigation"
diff --git a/.releaserc.yml b/.releaserc.yml
new file mode 100644
index 0000000..4360313
--- /dev/null
+++ b/.releaserc.yml
@@ -0,0 +1,22 @@
+plugins: [
+  "@semantic-release/commit-analyzer",
+  "@semantic-release/release-notes-generator",
+  "@semantic-release/gitlab",
+  "@semantic-release/changelog",    
+  [
+    "@semantic-release/exec",
+    {
+      "prepareCmd": "./bumpversion.sh \"${lastRelease.version}\" \"${nextRelease.version}\" \"${nextRelease.type}\"",
+      "successCmd": "./post-release.sh \"${nextRelease.version}\""
+    }
+  ],
+  [
+    "@semantic-release/git",
+    {
+      "assets": ["*.md", "templates/*.yml"]
+    }
+  ]
+]
+branches:
+  - "master"
+tagFormat: "${version}"
\ No newline at end of file
diff --git a/CONTRIBUTE.md b/CONTRIBUTING.md
similarity index 97%
rename from CONTRIBUTE.md
rename to CONTRIBUTING.md
index 5a24023..5900002 100644
--- a/CONTRIBUTE.md
+++ b/CONTRIBUTING.md
@@ -5,6 +5,8 @@ We try to make it easy, and all contributions, even the smaller ones, are more t
 This includes bug reports, fixes, documentation, examples...
 But first, read this page (including the small print at the end).
 
+Contributions are available on https://gitlab.com/to-be-continuous/renovate
+
 ## Legal
 
 All original contributions to _to be continuous_ are licensed under the
diff --git a/README.md b/README.md
index 2821555..779799b 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,39 @@
-# GitLab CI template Skeleton
+# GitLab CI template for Renovate
 
-This is a skeleton project for starting a new _to be continuous_ template.
+Automate your dependency updates with [Renovate](https://www.mend.io/renovate/).
 
-You shall fork it when you want to start developing a new template.
+## Usage
 
-Based on the kind of template (build, analyse, hosting, acceptance, ...), you should start working from one of the available `initial-xxx` branches, that each implement basic stuff.
+In order to include this template in your project, add the following to your `gitlab-ci.yml`:
 
+```yaml
+include:
+  - project: 'to-be-continuous/renovate'
+    ref: '1.0.0'
+    file: '/templates/gitlab-ci-renovate.yml'
+```
+
+## Configuration
+
+The Renovate template uses some global configuration used throughout all jobs.
+
+| Name                   | description                                                                     | default value     |
+|------------------------|---------------------------------------------------------------------------------|-------------------|
+| `RENOVATE_IMAGE`       | The Docker image used to run Renovate                                           | `registry.hub.docker.com/renovate/renovate:latest` |
+| :lock: `RENOVATE_TOKEN`| A GitLab access token to allow Renovate crawl your projects. [See doc](https://docs.renovatebot.com/modules/platform/gitlab/#authentication) | _none_ |
+| :lock: `GITHUB_COM_TOKEN`| A GitHub access token to allow Renovate fetch changelogs. [See doc](https://docs.renovatebot.com/getting-started/running/#githubcom-token-for-changelogs) | _none_ |
+
+This template will help you using [Renovate](https://www.mend.io/renovate/) from a GitLab project to
+automate your dependency updates within your groups or projects.
+On the contrary to other to-be-continuous templates, this one should be used in a separate project that
+will be in charge of crawling all your other projects.
+
+Upon including the template, carefuly follow [Renovate's documentation](https://docs.renovatebot.com/) to
+configure the bot accordingly. Pay attention to the following:
+
+* Remember to set the [platform](https://docs.renovatebot.com/self-hosted-configuration/#platform) parameter
+  to `gitlab` in your configuration.
+* [GitLab platform integration](https://docs.renovatebot.com/modules/platform/gitlab/) requires that you
+  declare a `RENOVATE_TOKEN` variable with an access token.
+* You'll also probaly need to declare a `GITHUB_COM_TOKEN` variable, holding a GitHub access token 
+  (for [fetching changelogs](https://docs.renovatebot.com/getting-started/running/#githubcom-token-for-changelogs))
diff --git a/Renovate.r2.yml b/Renovate.r2.yml
new file mode 100644
index 0000000..c9abda5
--- /dev/null
+++ b/Renovate.r2.yml
@@ -0,0 +1,13 @@
+files:
+    template: ./templates/gitlab-ci-renovate.yml
+    documentation: ./README.md
+    changelog: ./CHANGELOG.md
+data:
+    description: "Automate your dependency updates with Renovate"
+    public: true
+    labels:
+    - to be continuous
+    - Renovate
+    - Dependency Updates
+    license: LGPL v3
+    deprecated: false
\ No newline at end of file
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000..7829ff1
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,14 @@
+# Security Policy
+
+## Supported Versions
+
+Security fixes and updates are only applied to the latest released version. So always try to be up to date.
+
+## Reporting a Vulnerability
+
+In order to minimize risks of attack while investigating and fixing the issue, any vulnerability shall be reported by 
+opening a [**confidential** issue on gitlab.com](https://gitlab.com/to-be-continuous/renovate/-/issues/new?issue[confidential]=true&issue[description]=%28type+in+the+vulnerability+details+here%29%0A%0A%2Flabel%20~%22kind%3A%3Avulnerability%22).
+
+Follow-up and fixing will be made on a _best effort_ basis.
+
+If you have doubts about a potential vulnerability, please reach out one of the maintainers on Discord.
diff --git a/bumpversion.sh b/bumpversion.sh
new file mode 100755
index 0000000..f06829a
--- /dev/null
+++ b/bumpversion.sh
@@ -0,0 +1,41 @@
+#!/usr/bin/env bash
+
+function log_info() {
+  >&2 echo -e "[\\e[1;94mINFO\\e[0m] $*"
+}
+
+function log_warn() {
+  >&2 echo -e "[\\e[1;93mWARN\\e[0m] $*"
+}
+
+function log_error() {
+  >&2 echo -e "[\\e[1;91mERROR\\e[0m] $*"
+}
+
+# check number of arguments
+if [[ "$#" -le 2 ]]; then
+  log_error "Missing arguments"
+  log_error "Usage: $0 <current version> <next version>"
+  exit 1
+fi
+
+curVer=$1
+nextVer=$2
+relType=$3
+
+if [[ "$curVer" ]]; then
+  log_info "Bump version from \\e[33;1m${curVer}\\e[0m to \\e[33;1m${nextVer}\\e[0m (release type: $relType)..."
+
+  # replace in README
+  sed -e "s/ref: '$curVer'/ref: '$nextVer'/" README.md > README.md.next
+  mv -f README.md.next README.md
+
+  # replace in template and variants
+  for tmpl in templates/*.yml
+  do
+    sed -e "s/\"$curVer\"/\"$nextVer\"/" "$tmpl" > "$tmpl.next"
+    mv -f "$tmpl.next" "$tmpl"
+  done
+else
+  log_info "Bump version to \\e[33;1m${nextVer}\\e[0m (release type: $relType): this is the first release (skip)..."
+fi
diff --git a/kicker.json b/kicker.json
new file mode 100644
index 0000000..c1cb213
--- /dev/null
+++ b/kicker.json
@@ -0,0 +1,23 @@
+{
+  "name": "Renovate",
+  "description": "Automate your dependency updates with [Renovate](https://www.mend.io/renovate/)",
+  "template_path": "templates/gitlab-ci-renovate.yml",
+  "kind": "misc",
+  "variables": [
+    {
+      "name": "RENOVATE_IMAGE",
+      "description": "The Docker image used to run Renovate",
+      "default": "registry.hub.docker.com/renovate/renovate:latest"
+    },
+    {
+      "name": "RENOVATE_TOKEN",
+      "description": "A GitLab access token to allow Renovate crawl your projects. [See doc](https://docs.renovatebot.com/modules/platform/gitlab/#authentication)",
+      "secret": true
+    },
+    {
+      "name": "GITHUB_COM_TOKEN",
+      "description": "A GitHub access token to allow Renovate fetch changelogs. [See doc](https://docs.renovatebot.com/getting-started/running/#githubcom-token-for-changelogs)",
+      "secret": true
+    }
+  ]
+}
diff --git a/logo.png b/logo.png
index 1d49ae4c533c608703bafbc7d380cac36a97fc9f..70753a173ed09089752a12e8a2006dc8dfc927c2 100644
GIT binary patch
literal 5364
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

literal 11231
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
PbC95?tDnm{r-UW|$n1aR

diff --git a/post-release.sh b/post-release.sh
new file mode 100755
index 0000000..6d19786
--- /dev/null
+++ b/post-release.sh
@@ -0,0 +1,35 @@
+#!/usr/bin/env bash
+
+function log_info() {
+  >&2 echo -e "[\\e[1;94mINFO\\e[0m] $*"
+}
+
+function log_warn() {
+  >&2 echo -e "[\\e[1;93mWARN\\e[0m] $*"
+}
+
+function log_error() {
+  >&2 echo -e "[\\e[1;91mERROR\\e[0m] $*"
+}
+
+# check number of arguments
+if [[ "$#" -lt 1 ]]; then
+  log_error "Missing arguments"
+  log_error "Usage: $0 <next version>"
+  exit 1
+fi
+
+nextVer=$1
+minorVer=${nextVer%\.[0-9]*}
+majorVer=${nextVer%\.[0-9]*\.[0-9]*}
+
+log_info "Creating minor version tag alias \\e[33;1m${minorVer}\\e[0m from $nextVer..."
+git tag --force -a "$minorVer" "$nextVer" -m "Minor version alias (targets $nextVer)"
+
+log_info "Creating major version tag alias \\e[33;1m${majorVer}\\e[0m from $nextVer..."
+git tag --force -a "$majorVer" "$nextVer" -m "Major version alias (targets $nextVer)"
+
+log_info "Pushing tags..."
+git_base_url=$(echo "$CI_REPOSITORY_URL" | cut -d\@ -f2)
+git_auth_url="https://token:${GITLAB_TOKEN}@${git_base_url}"
+git push --tags --force "$git_auth_url"
diff --git a/templates/gitlab-ci-renovate.yml b/templates/gitlab-ci-renovate.yml
new file mode 100644
index 0000000..fb60793
--- /dev/null
+++ b/templates/gitlab-ci-renovate.yml
@@ -0,0 +1,265 @@
+# =========================================================================================
+# Copyright (C) 2021 Orange & contributors
+#
+# This program is free software; you can redistribute it and/or modify it under the terms
+# of the GNU Lesser General Public License as published by the Free Software Foundation;
+# either version 3 of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along with this
+# program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+# Floor, Boston, MA  02110-1301, USA.
+# =========================================================================================
+# default workflow rules: Merge Request pipelines
+workflow:
+  rules:
+    # prevent branch pipeline when an MR is open (prefer MR pipeline)
+    - if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'
+      when: never
+    - if: '$CI_COMMIT_MESSAGE =~ "/\[(ci skip|skip ci) on ([^],]*,)*tag(,[^],]*)*\]/" && $CI_COMMIT_TAG'
+      when: never
+    - if: '$CI_COMMIT_MESSAGE =~ "/\[(ci skip|skip ci) on ([^],]*,)*branch(,[^],]*)*\]/" && $CI_COMMIT_BRANCH'
+      when: never
+    - if: '$CI_COMMIT_MESSAGE =~ "/\[(ci skip|skip ci) on ([^],]*,)*mr(,[^],]*)*\]/" && $CI_MERGE_REQUEST_ID'
+      when: never
+    - if: '$CI_COMMIT_MESSAGE =~ "/\[(ci skip|skip ci) on ([^],]*,)*default(,[^],]*)*\]/" && $CI_COMMIT_REF_NAME =~ $CI_DEFAULT_BRANCH'
+      when: never
+    - if: '$CI_COMMIT_MESSAGE =~ "/\[(ci skip|skip ci) on ([^],]*,)*prod(,[^],]*)*\]/" && $CI_COMMIT_REF_NAME =~ $PROD_REF'
+      when: never
+    - if: '$CI_COMMIT_MESSAGE =~ "/\[(ci skip|skip ci) on ([^],]*,)*integ(,[^],]*)*\]/" && $CI_COMMIT_REF_NAME =~ $INTEG_REF'
+      when: never
+    - if: '$CI_COMMIT_MESSAGE =~ "/\[(ci skip|skip ci) on ([^],]*,)*dev(,[^],]*)*\]/" && $CI_COMMIT_REF_NAME !~ $PROD_REF && $CI_COMMIT_REF_NAME !~ $INTEG_REF'
+      when: never
+    - when: always
+
+
+variables:
+  # variabilized tracking image
+  TBC_TRACKING_IMAGE: "$CI_REGISTRY/to-be-continuous/tools/tracking:master"
+
+  RENOVATE_IMAGE: "registry.hub.docker.com/renovate/renovate:latest"
+  RENOVATE_ENDPOINT: $CI_API_V4_URL
+  
+  RENOVATE_LOG_FILE: renovate-log.ndjson
+  RENOVATE_AUTODISCOVER_FILTER: '${CI_PROJECT_ROOT_NAMESPACE}/**'
+  RENOVATE_BINARY_SOURCE: install
+  RENOVATE_LOG_FILE_LEVEL: debug
+  LOG_LEVEL: info
+
+.renovate-scripts: &renovate-scripts |
+  # BEGSCRIPT
+  set -e
+
+  function log_info() {
+      echo -e "[\\e[1;94mINFO\\e[0m] $*"
+  }
+
+  function log_warn() {
+      echo -e "[\\e[1;93mWARN\\e[0m] $*"
+  }
+
+  function log_error() {
+      echo -e "[\\e[1;91mERROR\\e[0m] $*"
+  }
+
+  function assert_defined() {
+    if [[ -z "$1" ]]
+    then
+      log_error "$2"
+      exit 1
+    fi
+  }
+
+  function install_ca_certs() {
+    certs=$1
+    if [[ -z "$certs" ]]
+    then
+      return
+    fi
+
+    if [[ ! "$(whoami)" == "root" ]]
+    then
+      log_warn "can't install custom CA certificates (not root user); make sure to handle it"
+      return
+    fi
+
+    # List of typical bundles
+    bundles="/etc/ssl/certs/ca-certificates.crt"                            # Debian/Ubuntu/Gentoo etc.
+    bundles="${bundles} /etc/ssl/cert.pem"                                  # Alpine Linux
+    bundles="${bundles} /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem"  # CentOS/RHEL 7
+    bundles="${bundles} /etc/pki/tls/certs/ca-bundle.crt"                   # Fedora/RHEL 6
+    bundles="${bundles} /etc/ssl/ca-bundle.pem"                             # OpenSUSE
+    bundles="${bundles} /etc/pki/tls/cacert.pem"                            # OpenELEC
+
+    # Try to find the right bundle to update it with custom CA certificates
+    for bundle in ${bundles}
+    do
+      # import if bundle exists
+      if [[ -f "${bundle}" ]]
+      then
+        # Import certificates in bundle
+        echo "${certs}" | tr -d '\r' >> "${bundle}"
+
+        log_info "Custom CA certificates imported in \\e[33;1m${bundle}\\e[0m"
+        ca_imported=1
+        break
+      fi
+    done
+
+    if [[ -z "$ca_imported" ]]
+    then
+      log_warn "Could not import custom CA certificates !"
+    fi
+  }
+
+  function unscope_variables() {
+    _scoped_vars=$(env | awk -F '=' "/^scoped__[a-zA-Z0-9_]+=/ {print \$1}" | sort)
+    if [[ -z "$_scoped_vars" ]]; then return; fi
+    log_info "Processing scoped variables..."
+    for _scoped_var in $_scoped_vars
+    do
+      _fields=${_scoped_var//__/:}
+      _condition=$(echo "$_fields" | cut -d: -f3)
+      case "$_condition" in
+      if) _not="";;
+      ifnot) _not=1;;
+      *)
+        log_warn "... unrecognized condition \\e[1;91m$_condition\\e[0m in \\e[33;1m${_scoped_var}\\e[0m"
+        continue
+      ;;
+      esac
+      _target_var=$(echo "$_fields" | cut -d: -f2)
+      _cond_var=$(echo "$_fields" | cut -d: -f4)
+      _cond_val=$(eval echo "\$${_cond_var}")
+      _test_op=$(echo "$_fields" | cut -d: -f5)
+      case "$_test_op" in
+      defined)
+        if [[ -z "$_not" ]] && [[ -z "$_cond_val" ]]; then continue;
+        elif [[ "$_not" ]] && [[ "$_cond_val" ]]; then continue;
+        fi
+        ;;
+      equals|startswith|endswith|contains|in|equals_ic|startswith_ic|endswith_ic|contains_ic|in_ic)
+        # comparison operator
+        # sluggify actual value
+        _cond_val=$(echo "$_cond_val" | tr '[:punct:]' '_')
+        # retrieve comparison value
+        _cmp_val_prefix="scoped__${_target_var}__${_condition}__${_cond_var}__${_test_op}__"
+        _cmp_val=${_scoped_var#"$_cmp_val_prefix"}
+        # manage 'ignore case'
+        if [[ "$_test_op" == *_ic ]]
+        then
+          # lowercase everything
+          _cond_val=$(echo "$_cond_val" | tr '[:upper:]' '[:lower:]')
+          _cmp_val=$(echo "$_cmp_val" | tr '[:upper:]' '[:lower:]')
+        fi
+        case "$_test_op" in
+        equals*)
+          if [[ -z "$_not" ]] && [[ "$_cond_val" != "$_cmp_val" ]]; then continue;
+          elif [[ "$_not" ]] && [[ "$_cond_val" == "$_cmp_val" ]]; then continue;
+          fi
+          ;;
+        startswith*)
+          if [[ -z "$_not" ]] && [[ "$_cond_val" != "$_cmp_val"* ]]; then continue;
+          elif [[ "$_not" ]] && [[ "$_cond_val" == "$_cmp_val"* ]]; then continue;
+          fi
+          ;;
+        endswith*)
+          if [[ -z "$_not" ]] && [[ "$_cond_val" != *"$_cmp_val" ]]; then continue;
+          elif [[ "$_not" ]] && [[ "$_cond_val" == *"$_cmp_val" ]]; then continue;
+          fi
+          ;;
+        contains*)
+          if [[ -z "$_not" ]] && [[ "$_cond_val" != *"$_cmp_val"* ]]; then continue;
+          elif [[ "$_not" ]] && [[ "$_cond_val" == *"$_cmp_val"* ]]; then continue;
+          fi
+          ;;
+        in*)
+          if [[ -z "$_not" ]] && [[ "__${_cmp_val}__" != *"__${_cond_val}__"* ]]; then continue;
+          elif [[ "$_not" ]] && [[ "__${_cmp_val}__" == *"__${_cond_val}__"* ]]; then continue;
+          fi
+          ;;
+        esac
+        ;;
+      *)
+        log_warn "... unrecognized test operator \\e[1;91m${_test_op}\\e[0m in \\e[33;1m${_scoped_var}\\e[0m"
+        continue
+        ;;
+      esac
+      # matches
+      _val=$(eval echo "\$${_target_var}")
+      log_info "... apply \\e[32m${_target_var}\\e[0m from \\e[32m\$${_scoped_var}\\e[0m${_val:+ (\\e[33;1moverwrite\\e[0m)}"
+      _val=$(eval echo "\$${_scoped_var}")
+      export "${_target_var}"="${_val}"
+    done
+    log_info "... done"
+  }
+
+  unscope_variables
+
+  # ENDSCRIPT
+
+stages:
+  - build
+  - test
+  - package-build
+  - package-test
+  - infra
+  - deploy
+  - acceptance
+  - publish
+  - infra-prod
+  - production
+
+.renovate-base:
+  image: $RENOVATE_IMAGE
+  services:
+    - name: "$TBC_TRACKING_IMAGE"
+      command: ["--service", "renovate", "1.0.0" ]
+  variables:
+    RENOVATE_BASE_DIR: $CI_PROJECT_DIR
+    RENOVATE_CACHE_DIR: $CI_PROJECT_DIR/.cache/renovate
+  # Cache downloaded dependencies and plugins between builds.
+  # To keep cache across branches add 'key: "$CI_JOB_NAME"'
+  # TODO (if necessary): define cache policy here
+  cache:
+    key: ${CI_COMMIT_REF_SLUG}-renovate
+    paths:
+      - .cache/renovate/**
+  before_script:
+    - *renovate-scripts
+    - install_ca_certs "${CUSTOM_CA_CERTS:-$DEFAULT_CA_CERTS}"
+
+# (example) validator job
+renovate-validator:
+  extends: .renovate-base
+  stage: build
+  # force no dependency
+  dependencies: []
+  script:
+    - renovate-config-validator
+
+# dependency check job: on manual or schedule (dry-run otherwise)
+renovate-depcheck:
+  extends: .renovate-base
+  stage: test
+  # force no dependency
+  dependencies: []
+  variables:
+    # dry-run by default
+    RENOVATE_DRY_RUN: "true"
+  script:
+    - renovate $RENOVATE_EXTRA_FLAGS
+  artifacts:
+    when: always
+    expire_in: 1d
+    paths:
+      - "$RENOVATE_LOG_FILE"
+  rules:
+    # not dry run on manual or schedule
+    - if: '$CI_PIPELINE_SOURCE == "schedule" || $CI_PIPELINE_SOURCE == "web"'
+      variables:
+        RENOVATE_DRY_RUN: "false"
+    - if: $RENOVATE_TOKEN
-- 
GitLab