From 9d2906203e30de7d89b079bfc041e3baab842418 Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone <exarkun@twistedmatrix.com> Date: Fri, 22 Jul 2022 13:39:28 -0400 Subject: [PATCH] first attempt at develop-to-production merge bot --- .gitlab-ci.yml | 10 +++++ ci-tools/update-production | 87 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 ci-tools/update-production diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 210486ac..a1ac2ba2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -167,3 +167,13 @@ update-nixpkgs: "$CI_PROJECT_PATH" \ "$CI_PROJECT_ID" \ "$CI_DEFAULT_BRANCH" + +update-production: + <<: *RUN_ON_MERGE_REQUEST + script: + - | + ./ci-tools/update-production \ + "$CI_SERVER_URL" \ + "$CI_PROJECT_ID" \ + "develop" \ + "production diff --git a/ci-tools/update-production b/ci-tools/update-production new file mode 100644 index 00000000..e7cd557f --- /dev/null +++ b/ci-tools/update-production @@ -0,0 +1,87 @@ +#!/usr/bin/env nix-shell +#!nix-shell -i bash -p git curl + +set -eux -o pipefail + +main() { + local TOKEN=$1 + shift + local SERVER_URL=$1 + shift + local PROJECT_ID=$1 + shift + local SOURCE_BRANCH=$1 + shift + local TARGET_BRANCH=$1 + shift + + # If there have been no changes we'll just abandon this update. + ensure_changes "$SOURCE_BRANCH" "$TARGET_BRANCH" + + local NOTES=$(compute_notes_diff "$SOURCE_BRANCH" "$TARGET_BRANCH") + + create_merge_request "$TOKEN" "$SERVER_URL" "$PROJECT_ID" "$SOURCE_BRANCH" "$TARGET_BRANCH" "$NOTES" +} + +ensure_changes() { + local SOURCE_BRANCH=$1 + shift + local TARGET_BRANCH=$1 + shift + + if [ $(git rev-parse "$SOURCE_BRANCH") -eq $(git rev-parse "$TARGET_BRANCH") ]; then + echo "No changes." + exit 0 + fi +} + +compute_notes_diff() { + local SOURCE_BRANCH=$1 + shift + local TARGET_BRANCH=$1 + shift + + git diff origin/"$SOURCE_BRANCH"...origin/"$TARGET_BRANCH" -- DEPLOYMENT-NOTES.rst +} + +create_merge_request() { + local TOKEN=$1 + shift + local SERVER_URL=$1 + shift + local PROJECT_ID=$1 + shift + # THe source branch of the MR. + local SOURCE_BRANCH=$1 + shift + # The target branch of the MR. + local TARGET_BRANCH=$1 + shift + local NOTES=$1 + shift + + local BODY=$(python3 -c ' +import sys, json +print(json.dumps({ + "id": sys.argv[1], + "source_branch": sys.argv[2], + "target_branch": sys.argv[3], + "remove_source_branch": True, + "title": f"update {sys.argv[3]}", + "description": f"```diff\n{sys.argv[4]}\n```", +})) +' "$PROJECT_ID" "$SOURCE_BRANCH" "$TARGET_BRANCH" "$NOTES") + + curl --verbose -X POST --data "${BODY}" --header "Content-Type: application/json" --header "PRIVATE-TOKEN: ${TOKEN}" "${SERVER_URL}/api/v4/projects/${PROJECT_ID}/merge_requests" +} + +# Pull the GitLab token from the environment here so we can work with them as +# arguments everywhere else. They're passed to us in the environment because +# *maybe* this is *slightly* safer than passing them in argv. +TOKEN="$UPDATE_PRODUCTION_PRIVATE_TOKEN" + +# Before proceeding, remove the secrets from our environment so we don't pass +# them to child processes - none of which need them. +unset UPDATE_PRODUCTION_PRIVATE_TOKEN + +main "$TOKEN" "$@" -- GitLab