diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..7c0aade41bc47869e70fc205370f1aa566918443
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,23 @@
+---
+stages:
+  - release
+
+
+# Automated month-based releases
+release-branch:
+  stage: release
+  image: registry.gitlab.com/gitlab-org/release-cli
+  variables:
+    GIT_STRATEGY: clone
+    GIT_DEPTH: 0
+  before_script:
+    - apk add --no-cache git
+    - export INFRA_RELEASE_VERSION="$(date +%y.%m)"
+    - export INFRA_RELEASE_NAME="GitOps Infrastructure $INFRA_RELEASE_VERSION"
+    - export INFRA_RELEASE_DESCRIPTION="$(printf '## Changelog\n\n' && git log --no-merges --pretty="- %s (%h)" "HEAD...$(git tag | sort -V -r | head -1)" && printf '\n\n## External Contributors\n\n' && git log --pretty="- %an%n- %cn" HEAD...$(git tag | sort -V -r | head -1) | sort | uniq | grep -v 'Sheogorath' && printf "\n\n---\n*This is an automated release. See [#${CI_JOB_ID}]($CI_JOB_URL) for details.*")"
+  script:
+    - >
+      release-cli create --name "$INFRA_RELEASE_NAME" --description "$INFRA_RELEASE_DESCRIPTION"
+      --tag-name "v${INFRA_RELEASE_VERSION}" --ref $CI_COMMIT_SHA
+  rules:
+    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $INFRA_RELEASE_NOW == "true" && $CI_COMMIT_TAG == null'