Commit e3886ffd authored by Boris Barnier's avatar Boris Barnier Committed by Pierre Smeyers
Browse files

feat: synchronize releases

Releases are required to integrate the CI/CD Catalog
parent cf34b410
Loading
Loading
Loading
Loading
+21 −13
Original line number Diff line number Diff line
@@ -24,12 +24,14 @@ gitlab-sync.sh \
   [--dest-sync-path {GitLab destination root group path to synchronize}] \
   [--max-visibility {max visibility}] \
   [--exclude {coma separated list of project/group path(s) to exclude}] \
   [--insecure] \
   [--update-release] \
   [--no-group-description {do not synchronise group description}] \
   [--no-project-description {do not synchronise project description}]
```

| CLI option                 | Env. Variable                    | Description                                                                                                           | Default Value                                                    |
| --------------------- | -------------------- | -------------------------------------- | ----------------- |
|----------------------------|----------------------------------|-----------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------|
| `--src-api`                | `$SRC_GITLAB_API`                | GitLab source API url                                                                                                 | `https://gitlab.com/api/v4`                                      |
| `--src-token`              | `$SRC_TOKEN`                     | GitLab source token (_optional_ if source GitLab group and sub projects have `public` visibility)                     | _none_                                                           |
| `--src-sync-path`          | `$SRC_SYNC_PATH`                 | GitLab source root group path to synchronize                                                                          | `to-be-continuous`                                               |
@@ -38,6 +40,8 @@ gitlab-sync.sh \
| `--dest-sync-path`         | `$DEST_SYNC_PATH`                | GitLab destination root group path to synchronize                                                                     | guessed from GitLab CI env or `to-be-continuous`                 |
| `--max-visibility`         | `$MAX_VISIBILITY`                | maximum visibility of projects in destination group                                                                   | `$CI_PROJECT_VISIBILITY` (when running in GitLab CI) or `public` |
| `--exclude`                | `$EXCLUDE`                       | coma separated list of project/group path(s) to exclude                                                               | _none_                                                           |
| `--insecure`               | `$INSECURE`                      | set to skip TLS check on curl requests                                                                                | `false`                                                          |
| `--update-release`         | `$UPDATE_RELEASE`                | set to update the releases even if they exists                                                                        | `false`                                                          |
| `--no-group-description`   | `$GROUP_DESCRIPTION_DISABLED`    | do not synchronise group description                                                                                  | _none_                                                           |
| `--no-project-description` | `$PROJECT_DESCRIPTION_DISABLED`  | do not synchronise project description                                                                                | _none_                                                           |

@@ -56,3 +60,7 @@ Once copied _to be continuous_ to your GitLab server, you shall then schedule a
The script will only require a GitLab token, that shall be configured declaring a `$GITLAB_TOKEN` CI/CD project variable. (`--dest-api` will be implicitly retrieved using predefined `$CI_API_V4_URL`).

You can define a custom alpine image to use by setting `$GITLAB_SYNC_IMAGE` (default to `registry.hub.docker.com/alpine:latest`)

## CI/CD Catalog

To use _to be continuous_ templates as CI/CD Catalog resources on a your GitLab Server, you have to manually activate the _CI/CD Catalog resource_ option in `Settings`/`General`/`Visibility, project features, permissions`. 
 No newline at end of file
+63 −0
Original line number Diff line number Diff line
@@ -102,6 +102,52 @@ function maybe_create_group() {
  echo "$group_json" | jq -r '.id'
}


# Synchronize a Release for a project
# $1: destination project ID
# $2: source project ID
# $3: release tag name
function sync_release(){
  dest_project_id=$1
  src_project_id=$2
  tag_name=$3

  log_info "Synchronizing release \\e[33;1m${tag_name}\\e[0m to project ID \\e[33;1m${dest_project_id}\\e[0m)"
  src_release=$(curl ${INSECURE:+-k} -sSf -H "${SRC_TOKEN:+PRIVATE-TOKEN: $SRC_TOKEN}" "$SRC_GITLAB_API/projects/$src_project_id/releases/$tag_name")

  dest_release_status=$(curl ${INSECURE:+-k} -s -o /dev/null -I -w "%{http_code}" -H "${DEST_TOKEN:+PRIVATE-TOKEN: $DEST_TOKEN}" "$DEST_GITLAB_API/projects/$dest_project_id/releases/$tag_name")
  if [[ "$dest_release_status" == 404* ]]
  then
    # dest release does not exist: create
    curl ${INSECURE:+-k} -sSf -H "${DEST_TOKEN:+PRIVATE-TOKEN: $DEST_TOKEN}" -H "Content-Type: application/json" -X POST "$DEST_GITLAB_API/projects/$dest_project_id/releases" \
      --data "{
        \"tag_name\": \"$tag_name\",
        \"name\": \"$tag_name\",
        \"released_at\": $(echo "$src_release" | jq .released_at),
        \"description\": $(echo "$src_release" | jq .description)
      }" >/dev/null
  elif [[ "$dest_release_status" == 200* ]]
  then
    if [[ "$UPDATE_RELEASE" == "true" ]]
    then
      log_info "... release \\e[33;1m$tag_name\\e[0m exists: update"
      # dest release does not exist: create
      curl ${INSECURE:+-k} -sSf -H "${DEST_TOKEN:+PRIVATE-TOKEN: $DEST_TOKEN}" -H "Content-Type: application/json" -X PUT "$DEST_GITLAB_API/projects/$dest_project_id/releases/$tag_name" \
        --data "{
          \"tag_name\": \"$tag_name\",
          \"name\": \"$tag_name\",
          \"released_at\": $(echo "$src_release" | jq .released_at),
          \"description\": $(echo "$src_release" | jq .description)
        }" >/dev/null
    else
      log_info "... release \\e[33;1m$tag_name\\e[0m exists: skip"
    fi
  else
    # another error: abort
    fail "... unexpected error: $dest_release_status"
  fi
}

# Synchronizes a GitLab project
# $1: source project JSON
# $2: destination parent group ID (number)
@@ -127,6 +173,8 @@ function sync_project() {
    then
      # dest project does not exist: create (disable MR and issues as they are cloned projects)
      log_info "... destination project not found: create with visibility \\e[33;1m${dest_visibility}\\e[0m"
      # TODO enable project as a ci catalog resource
      # It seems that the option isn't present in the REST API for now
      dest_project_json=$(curl ${INSECURE:+-k} -sSf -H "${DEST_TOKEN:+PRIVATE-TOKEN: $DEST_TOKEN}" -H "Content-Type: application/json" -X POST "$DEST_GITLAB_API/projects" \
        --data "{
          \"path\": $(echo "$src_project_json" | jq .path),
@@ -143,12 +191,16 @@ function sync_project() {
      log_info "... destination project found: synchronize"
      if [[ "${PROJECT_DESCRIPTION_DISABLED}" == "true" ]]
      then
        # TODO enable project as a ci catalog resource
        # It seems that the option isn't present in the REST API for now
        dest_project_json=$(curl ${INSECURE:+-k} -sSf -H "${DEST_TOKEN:+PRIVATE-TOKEN: $DEST_TOKEN}" -H "Content-Type: application/json" -X PUT "$DEST_GITLAB_API/projects/$dest_project_id" \
          --data "{
            \"name\": $(echo "$src_project_json" | jq .name),
            \"visibility\": \"$dest_visibility\"
          }")
      else
        # TODO enable project as a ci catalog resource
        # It seems that the option isn't present in the REST API for now
        dest_project_json=$(curl ${INSECURE:+-k} -sSf -H "${DEST_TOKEN:+PRIVATE-TOKEN: $DEST_TOKEN}" -H "Content-Type: application/json" -X PUT "$DEST_GITLAB_API/projects/$dest_project_id" \
          --data "{
            \"name\": $(echo "$src_project_json" | jq .name),
@@ -220,6 +272,11 @@ function sync_project() {
      log_info "... protect $src_default_branch branch"
      curl ${INSECURE:+-k} -sS -H "${DEST_TOKEN:+PRIVATE-TOKEN: $DEST_TOKEN}" -X POST "$DEST_GITLAB_API/projects/$dest_project_id/protected_branches?name=$src_default_branch" > /dev/null
    fi

    # 3: sync Releases
    curl ${INSECURE:+-k} -sSf -H "${SRC_TOKEN:+PRIVATE-TOKEN: $SRC_TOKEN}" "$SRC_GITLAB_API/projects/$src_project_id/releases?per_page=100" | jq -r '.[].tag_name' | while read -r release; do
      sync_release "$src_project_id" "$dest_project_id" "$release"
    done
  fi
}

@@ -372,6 +429,7 @@ case ${key} in
    log_info "  --src-api {GitLab source API url} [--src-token {GitLab source token}]"
    log_info "  --dest-api {GitLab destination API url} [--dest-token {GitLab destination token}]"
    log_info "  [--insecure]"
    log_info "  [--update-release]"
    log_info "  [--max-visibility {max visibility}]"
    log_info "  [--exclude {coma separated list of project/group path(s) to exclude}]"
    log_info "  [--no-group-description {do not synchronise group description}]"
@@ -432,6 +490,10 @@ case ${key} in
    INSECURE="true"
    shift # past argument
    ;;
    --update-release)
    UPDATE_RELEASE="true"
    shift # past argument
    ;;
    *)    # unknown option
    POSITIONAL+=("$1") # save it in an array for later
    shift # past argument
@@ -456,6 +518,7 @@ log_info "- to (--dest-api) : \\e[33;1m${DEST_GITLAB_API:-none (d
log_info "- max visi.   (--max-visibility) : \\e[33;1m${MAX_VISIBILITY}\\e[0m"
log_info "- exclude     (--exclude)        : \\e[33;1m${EXCLUDE:-none}\\e[0m"
log_info "- insecure    (--insecure)       : \\e[33;1m${INSECURE:-false}\\e[0m"
log_info "- update rel. (--update-release) : \\e[33;1m${UPDATE_RELEASE:-false}\\e[0m"
log_info "- disable group desc. sync   (--no-group-description)   : \\e[33;1m${GROUP_DESCRIPTION_DISABLED:-false}\\e[0m"
log_info "- disable project desc. sync (--no-project-description) : \\e[33;1m${PROJECT_DESCRIPTION_DISABLED:-false}\\e[0m"