Skip to content

chore: add admin mail management to delegated settings #128

chore: add admin mail management to delegated settings

chore: add admin mail management to delegated settings #128

# SPDX-FileCopyrightText: 2024 IONOS Productivity
# SPDX-License-Identifier: MIT
#
# This workflow automates submodule updates in ncw-server when PRs are merged to main.
#
# How it works:
# 1. Triggers when a PR with milestone "ncw-<nnn>" is merged to main in the submodule repo
# 2. Creates a pre-release in the submodule repository
# 3. Checks if branch "rc/ncw-<nnn>" exists in ncw-server
# 4. If rc branch exists:
# - Creates update branch from "rc/ncw-<nnn>"
# - Creates PR to merge into "rc/ncw-<nnn>"
# 5. If rc branch doesn't exist:
# - Creates update branch from BASE_BRANCH
# - Creates PR to merge into BASE_BRANCH
# 6. PR includes milestone attachment for tracking
#
# To adapt for other submodules:
# 1. Copy this workflow file to the submodule repository's .github/workflows/
# 2. Update the 'if' condition in create-submodule-pr job
# 3. Update the env variables in create-submodule-pr job:
# - SUBMODULE_NAME: Directory name in ncw-server (e.g., "IONOS")
# - SUBMODULE_REPO: Full repository name (e.g., "IONOS-Productivity/ncw-config")
# - TARGET_REPO: Where the submodule lives (typically "IONOS-Productivity/ncw-server")
# - BASE_BRANCH: Default target branch (typically "ionos-dev")
# - COMMIT_PREFIX: Commit message prefix (e.g., "IONOS(config)")
# - MILESTONE_PREFIX: Milestone prefix pattern (e.g., "ncw" for milestones like "ncw-3")
# 4. Ensure NCW_SERVER_PAT secret is configured in the submodule repository
#
name: Create pre-release and update ncw-server submodule
on:
push:
branches:
- main
workflow_dispatch:
permissions:
contents: write
pull-requests: write
jobs:
create-prerelease:
runs-on: [ubuntu-latest]
outputs:
sha: ${{ steps.commit-info.outputs.sha }}
short_sha: ${{ steps.commit-info.outputs.short_sha }}
tag_name: ${{ steps.commit-info.outputs.short_sha }}
release_url: ${{ steps.create-release.outputs.html_url }}
steps:
- name: Checkout repository
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Get commit information
id: commit-info
run: |
echo "sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
echo "short_sha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
- name: Check GitHub CLI installation
id: check-gh
run: |
if command -v gh &> /dev/null; then
echo "installed=true" >> $GITHUB_OUTPUT
else
echo "installed=false" >> $GITHUB_OUTPUT
fi
- name: Install GitHub CLI
if: steps.check-gh.outputs.installed != 'true'
run: |
echo "Installing GitHub CLI..."
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg
sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null
sudo apt update
sudo apt install gh -y
- name: Create pre-release
id: create-release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Check if the release already exists
if gh release view "${{ steps.commit-info.outputs.short_sha }}" --repo "${{ github.repository }}" > /dev/null 2>&1; then
# Release exists, get its URL
RELEASE_URL=$(gh release view "${{ steps.commit-info.outputs.short_sha }}" --repo "${{ github.repository }}" --json url -q ".url")
else
# Release does not exist, create it
RELEASE_URL=$(gh release create "${{ steps.commit-info.outputs.short_sha }}" \
--title "Pre-release ${{ steps.commit-info.outputs.short_sha }}" \
--generate-notes \
--prerelease \
--repo "${{ github.repository }}")
fi
echo "html_url=$RELEASE_URL" >> $GITHUB_OUTPUT
create-submodule-pr:
needs: create-prerelease
runs-on: [ubuntu-latest]
# Update this condition to match SUBMODULE_REPO when adapting for other submodules
if: github.repository == 'IONOS-Productivity/ncw-config'
env:
# Configuration for submodule updates - customize these values for different submodules
SUBMODULE_NAME: IONOS # Submodule directory name in ncw-server
SUBMODULE_REPO: IONOS-Productivity/ncw-config # Source repository (must match 'if' condition above)
TARGET_REPO: IONOS-Productivity/ncw-server # Target repository containing the submodule
BASE_BRANCH: ionos-dev # Default base branch for PRs
COMMIT_PREFIX: "IONOS(config)" # Prefix for commit messages and PR titles
MILESTONE_PREFIX: ncw # Milestone prefix (e.g., "ncw" for "ncw-3")
steps:
- name: Get milestone from merged PR
id: get-milestone
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Use GitHub API to get PRs associated with this commit
# This is more reliable than searching, as it uses commit-to-PR association
PR_DATA=$(gh api "repos/${{ github.repository }}/commits/${{ github.sha }}/pulls" \
--jq '[.[] | select(.merged_at != null)] | .[0] | {number: .number, milestone: .milestone.title}')
PR_NUMBER=$(echo "$PR_DATA" | jq -r '.number // empty')
MILESTONE=$(echo "$PR_DATA" | jq -r '.milestone // empty')
if [ -n "$PR_NUMBER" ]; then
echo "milestone=$MILESTONE" >> $GITHUB_OUTPUT
if [ -n "$MILESTONE" ]; then
echo "::notice::Found PR #$PR_NUMBER with milestone: $MILESTONE"
else
echo "::notice::Found PR #$PR_NUMBER but no milestone set"
fi
else
echo "milestone=" >> $GITHUB_OUTPUT
echo "::notice::No merged PR found for commit ${{ github.sha }}"
fi
- name: Checkout ncw-server repository
uses: actions/checkout@v5
with:
repository: ${{ env.TARGET_REPO }}
token: ${{ secrets.NCW_SERVER_PAT }}
ref: ${{ env.BASE_BRANCH }}
fetch-depth: 0
sparse-checkout: |
${{ env.SUBMODULE_NAME }}
.gitmodules
- name: Check GitHub CLI installation
id: check-gh
run: |
if command -v gh &> /dev/null; then
echo "installed=true" >> $GITHUB_OUTPUT
else
echo "installed=false" >> $GITHUB_OUTPUT
fi
- name: Install GitHub CLI
if: steps.check-gh.outputs.installed != 'true'
run: |
echo "Installing GitHub CLI..."
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg
sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null
sudo apt update
sudo apt install gh -y
- name: Update submodule
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
# Configure git to use HTTPS instead of SSH for GitHub
git config --global url."https://github.com/".insteadOf "git@github.com:"
git config --global url."https://".insteadOf "ssh://"
# Determine base branch from milestone
SELECTED_BASE_BRANCH="${{ env.BASE_BRANCH }}"
MILESTONE="${{ steps.get-milestone.outputs.milestone }}"
# Fetch all branches to check for rc branches
git fetch origin
if [ -n "$MILESTONE" ]; then
# Check if milestone matches pattern <prefix>-<nnn> (e.g., ncw-3)
MILESTONE_PATTERN="^${{ env.MILESTONE_PREFIX }}-[0-9]+$"
if [[ "$MILESTONE" =~ $MILESTONE_PATTERN ]]; then
RC_BRANCH="rc/$MILESTONE"
echo "::notice::Checking for release candidate branch: $RC_BRANCH"
# Check if rc branch exists
if git ls-remote --heads origin "$RC_BRANCH" | grep -q "$RC_BRANCH"; then
SELECTED_BASE_BRANCH="$RC_BRANCH"
echo "::notice::Using base branch: $SELECTED_BASE_BRANCH"
else
echo "::notice::Branch $RC_BRANCH not found, using ${{ env.BASE_BRANCH }}"
fi
else
echo "::notice::Milestone '$MILESTONE' doesn't match ${{ env.MILESTONE_PREFIX }}-<nnn> pattern, using ${{ env.BASE_BRANCH }}"
fi
else
echo "::notice::No milestone found, using ${{ env.BASE_BRANCH }}"
fi
# Create a new branch for the update directly from the selected base branch
# Replace slashes with dashes for cleaner branch names
SUBMODULE_NAME_CLEAN=$(echo "${{ env.SUBMODULE_NAME }}" | tr '/' '-')
BRANCH_NAME="update-${SUBMODULE_NAME_CLEAN}-submodule-${{ needs.create-prerelease.outputs.short_sha }}"
git checkout -B "$BRANCH_NAME" "origin/$SELECTED_BASE_BRANCH"
# Export the selected base branch for use in PR creation
echo "SELECTED_BASE_BRANCH=$SELECTED_BASE_BRANCH" >> $GITHUB_ENV
# Initialize only the target submodule
git submodule update --init "${{ env.SUBMODULE_NAME }}"
# Update the submodule to the new commit
cd "${{ env.SUBMODULE_NAME }}"
git fetch origin main
git checkout ${{ needs.create-prerelease.outputs.sha }}
# Get the commit message for description
COMMIT_MSG=$(git log -1 --pretty=format:'%s')
cd ..
# Commit the submodule update with release link
RELEASE_URL="https://github.com/${{ env.SUBMODULE_REPO }}/releases/tag/${{ needs.create-prerelease.outputs.short_sha }}"
git add "${{ env.SUBMODULE_NAME }}"
git commit -m "${{ env.COMMIT_PREFIX }}: update submodule ${{ needs.create-prerelease.outputs.short_sha }} ($COMMIT_MSG)" \
-m "" \
-m "$RELEASE_URL" \
-m "" \
-m "Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>"
# Push the branch
git push origin "$BRANCH_NAME"
- name: Create Pull Request
env:
GH_TOKEN: ${{ secrets.NCW_SERVER_PAT }}
run: |
# Replace slashes with dashes for cleaner branch names
SUBMODULE_NAME_CLEAN=$(echo "${{ env.SUBMODULE_NAME }}" | tr '/' '-')
BRANCH_NAME="update-${SUBMODULE_NAME_CLEAN}-submodule-${{ needs.create-prerelease.outputs.short_sha }}"
MILESTONE="${{ steps.get-milestone.outputs.milestone }}"
# Get the commit message from submodule
cd "${{ env.SUBMODULE_NAME }}"
COMMIT_MSG=$(git log -1 --pretty=format:'%s')
cd ..
RELEASE_URL="https://github.com/${{ env.SUBMODULE_REPO }}/releases/tag/${{ needs.create-prerelease.outputs.short_sha }}"
# Build PR body with milestone info if available
PR_BODY="${{ env.COMMIT_PREFIX }}: update submodule ${{ needs.create-prerelease.outputs.short_sha }} ($COMMIT_MSG)
$RELEASE_URL"
if [ -n "$MILESTONE" ]; then
PR_BODY="$PR_BODY
Milestone: $MILESTONE"
fi
PR_BODY="$PR_BODY
---
Auto-generated PR from ${{ env.SUBMODULE_NAME }} repository merge to main branch."
# Check if a PR already exists for this branch
EXISTING_PR_URL=$(gh pr list \
--repo "${{ env.TARGET_REPO }}" \
--head "$BRANCH_NAME" \
--state open \
--json url \
--jq '.[0].url')
if [ -n "$EXISTING_PR_URL" ]; then
PR_URL="$EXISTING_PR_URL"
echo "::notice::PR already exists: $PR_URL"
else
# Create PR with milestone if available
# Use the same base branch that was used to create the update branch
if [ -z "$SELECTED_BASE_BRANCH" ]; then
echo "::error::SELECTED_BASE_BRANCH is not set. Expected previous step to define it."
exit 1
fi
TARGET_BRANCH="$SELECTED_BASE_BRANCH"
if [ -n "$MILESTONE" ]; then
PR_URL=$(gh pr create \
--repo "${{ env.TARGET_REPO }}" \
--title "${{ env.COMMIT_PREFIX }}: update submodule ${{ needs.create-prerelease.outputs.short_sha }} ($COMMIT_MSG)" \
--body "$PR_BODY" \
--base "$TARGET_BRANCH" \
--head "$BRANCH_NAME" \
--milestone "$MILESTONE")
else
PR_URL=$(gh pr create \
--repo "${{ env.TARGET_REPO }}" \
--title "${{ env.COMMIT_PREFIX }}: update submodule ${{ needs.create-prerelease.outputs.short_sha }} ($COMMIT_MSG)" \
--body "$PR_BODY" \
--base "$TARGET_BRANCH" \
--head "$BRANCH_NAME")
fi
echo "::notice::Created PR: $PR_URL"
fi
log-details:
needs: [create-prerelease, create-submodule-pr]
runs-on: [ubuntu-latest]
if: always()
steps:
- name: Log workflow details
run: |
echo "::notice::✅ Created pre-release with tag ${{ needs.create-prerelease.outputs.tag_name }}"
echo "::notice::🔗 Release URL: ${{ needs.create-prerelease.outputs.release_url }}"
if [ "${{ needs.create-submodule-pr.result }}" == "success" ]; then
echo "::notice::📦 Submodule update PR created for ncw-server"
fi
echo "::notice::💾 Commit: ${{ needs.create-prerelease.outputs.sha }}"