Skip to content

Merge upstream prometheus/prometheus branch #57

Merge upstream prometheus/prometheus branch

Merge upstream prometheus/prometheus branch #57

name: Merge upstream prometheus/prometheus branch
on:
schedule:
- cron: "0 2 * * 1" # weekly at 2am on Monday
workflow_dispatch:
inputs:
upstream_branch:
description: "Upstream branch to merge from prometheus/prometheus"
required: true
default: "main"
type: string
local_branch:
description: "Local branch to merge into"
required: true
default: "main"
type: string
jobs:
check-merge:
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
merge_needed: ${{ steps.check-merge.outputs.merge_needed }}
upstream_branch: ${{ steps.set-branches.outputs.upstream_branch }}
local_branch: ${{ steps.set-branches.outputs.local_branch }}
timestamp: ${{ steps.set-branches.outputs.timestamp }}
upstream_commit: ${{ steps.get-upstream-info.outputs.upstream_commit }}
upstream_short: ${{ steps.get-upstream-info.outputs.upstream_short }}
commit_date: ${{ steps.get-upstream-info.outputs.commit_date }}
bot_branch: ${{ steps.set-branches.outputs.bot_branch }}
steps:
- name: Set default branches for scheduled runs
id: set-branches
env:
UPSTREAM_BRANCH: ${{ inputs.upstream_branch || 'main' }}
LOCAL_BRANCH: ${{ inputs.local_branch || 'main' }}
run: |
# Create timestamp for branch naming
TIMESTAMP=$(date +%Y%m%d%H%M)
# Compute bot branch name pattern
BOT_BRANCH="bot/$LOCAL_BRANCH/merge-upstream-$UPSTREAM_BRANCH-$TIMESTAMP"
echo "upstream_branch=$UPSTREAM_BRANCH" >> $GITHUB_OUTPUT
echo "local_branch=$LOCAL_BRANCH" >> $GITHUB_OUTPUT
echo "timestamp=$TIMESTAMP" >> $GITHUB_OUTPUT
echo "bot_branch=$BOT_BRANCH" >> $GITHUB_OUTPUT
echo "Upstream branch: $UPSTREAM_BRANCH"
echo "Local branch: $LOCAL_BRANCH"
echo "Bot branch: $BOT_BRANCH"
- name: Check out repository
uses: actions/checkout@v4
with:
ref: ${{ steps.set-branches.outputs.local_branch }}
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0
set-safe-directory: "*"
- name: Add prometheus/prometheus remote and fetch
env:
UPSTREAM_BRANCH: ${{ steps.set-branches.outputs.upstream_branch }}
run: |
echo "Adding prometheus/prometheus as remote..."
git remote add prometheus https://github.com/prometheus/prometheus.git
# Fetch the upstream branch
echo "Fetching branch $UPSTREAM_BRANCH from prometheus/prometheus..."
git fetch prometheus $UPSTREAM_BRANCH
# Verify the branch exists
if ! git show-ref --verify --quiet refs/remotes/prometheus/$UPSTREAM_BRANCH; then
echo "Error: Branch $UPSTREAM_BRANCH not found in prometheus/prometheus"
exit 1
fi
echo "Successfully fetched upstream branch $UPSTREAM_BRANCH"
- name: Get upstream commit info
id: get-upstream-info
env:
UPSTREAM_BRANCH: ${{ steps.set-branches.outputs.upstream_branch }}
run: |
# Get latest commit info from upstream branch
UPSTREAM_COMMIT=$(git rev-parse prometheus/$UPSTREAM_BRANCH)
UPSTREAM_SHORT=$(echo "$UPSTREAM_COMMIT" | cut -c1-12)
COMMIT_DATE=$(git log --format="%ad" --date=short -n 1 prometheus/$UPSTREAM_BRANCH)
echo "upstream_commit=$UPSTREAM_COMMIT" >> $GITHUB_OUTPUT
echo "upstream_short=$UPSTREAM_SHORT" >> $GITHUB_OUTPUT
echo "commit_date=$COMMIT_DATE" >> $GITHUB_OUTPUT
echo "Upstream commit: $UPSTREAM_COMMIT"
- name: Check if merge is needed
id: check-merge
env:
UPSTREAM_BRANCH: ${{ steps.set-branches.outputs.upstream_branch }}
LOCAL_BRANCH: ${{ steps.set-branches.outputs.local_branch }}
run: |
# Check if upstream has new commits
UPSTREAM_COMMIT=$(git rev-parse prometheus/$UPSTREAM_BRANCH)
# Check if we already have this commit
if git merge-base --is-ancestor $UPSTREAM_COMMIT HEAD; then
echo "merge_needed=false" >> $GITHUB_OUTPUT
echo "No new commits to merge from upstream $UPSTREAM_BRANCH"
else
echo "merge_needed=true" >> $GITHUB_OUTPUT
echo "New commits found in upstream $UPSTREAM_BRANCH"
# Show what would be merged
echo "Commits to be merged:"
git log --oneline HEAD..prometheus/$UPSTREAM_BRANCH | head -10
fi
attempt-merge:
runs-on: ubuntu-latest
needs: check-merge
if: needs.check-merge.outputs.merge_needed == 'true'
permissions:
contents: read
outputs:
merge_result: ${{ steps.merge-attempt.outputs.merge_result }}
steps:
- name: Check out repository
uses: actions/checkout@v4
with:
ref: ${{ needs.check-merge.outputs.local_branch }}
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0
set-safe-directory: "*"
- name: Add prometheus/prometheus remote and fetch
run: |
git remote add prometheus https://github.com/prometheus/prometheus.git
git fetch prometheus ${{ needs.check-merge.outputs.upstream_commit }}
- name: Attempt merge
id: merge-attempt
run: |
# Configure git for the merge
git config user.name "mimir-github-bot[bot]"
git config user.email "mimir-github-bot[bot]@users.noreply.github.com"
echo "Attempting to merge ${{ needs.check-merge.outputs.upstream_commit }}..."
# Attempt the merge
if git merge ${{ needs.check-merge.outputs.upstream_commit }} --no-edit; then
echo "merge_result=success" >> $GITHUB_OUTPUT
echo "Merge successful!"
git log --oneline -1
else
# Reset to clean state
git merge --abort
# Check if conflicts exist
git merge ${{ needs.check-merge.outputs.upstream_commit }} --no-commit --no-ff || true
if git diff --name-only --diff-filter=U | grep -q .; then
echo "merge_result=conflicts" >> $GITHUB_OUTPUT
echo "Merge conflicts detected in:"
git diff --name-only --diff-filter=U
else
echo "merge_result=error" >> $GITHUB_OUTPUT
echo "Merge failed for unknown reasons"
fi
git reset --hard HEAD
fi
handle-conflicts:
runs-on: ubuntu-latest
needs: [check-merge, attempt-merge]
if: needs.attempt-merge.outputs.merge_result == 'conflicts'
permissions:
contents: write
pull-requests: write
id-token: write
outputs:
pr_url: ${{ steps.create-conflict-pr.outputs.pull-request-url }}
steps:
- name: Check out repository
uses: actions/checkout@v4
with:
ref: ${{ needs.check-merge.outputs.local_branch }}
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0
set-safe-directory: "*"
- name: Create empty commit for PR
run: |
# Configure git
git config user.name "mimir-github-bot[bot]"
git config user.email "mimir-github-bot[bot]@users.noreply.github.com"
# Create an empty commit to establish the branch
git commit --allow-empty -m "Empty commit to create branch for conflict resolution"
# This job uses "mimir-github-bot" instead of "github-actions bot" (secrets.GITHUB_TOKEN)
# because any events triggered by the later don't spawn GitHub actions.
# Refer to https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication#using-the-github_token-in-a-workflow
- name: Retrieve GitHub App Credentials from Vault
id: get-secrets
uses: grafana/shared-workflows/actions/get-vault-secrets@28361cdb22223e5f1e34358c86c20908e7248760 # v1.1.0
with:
repo_secrets: |
APP_ID=mimir-github-bot:app_id
PRIVATE_KEY=mimir-github-bot:private_key
- name: Generate GitHub App Token
id: app-token
uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # v1.12.0
with:
app-id: ${{ env.APP_ID }}
private-key: ${{ env.PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
- name: Create empty PR for conflict resolution
id: create-conflict-pr
uses: peter-evans/create-pull-request@4e1beaa7521e8b457b572c090b25bd3db56bf1c5 # v5.0.3
with:
token: ${{ steps.app-token.outputs.token }}
title: "[${{ needs.check-merge.outputs.local_branch }}] Merge upstream prometheus/${{ needs.check-merge.outputs.upstream_branch }} to ${{ needs.check-merge.outputs.upstream_short }}"
body: |
## Merge Conflicts Detected
*This PR was automatically created by the [merge-upstream-prometheus workflow](https://github.com/grafana/mimir-prometheus/blob/main/.github/workflows/merge-upstream-prometheus.yml) due to merge conflicts.*
**For reviewers**: After conflicts are resolved, the author should post a comment with the output of `git show --remerge-diff`. This shows how merge conflicts were manually resolved compared to what Git would have done automatically, making conflict resolution transparent and allowing validation that conflicts were resolved correctly.
### Details
- **Upstream branch**: `${{ needs.check-merge.outputs.upstream_branch }}`
- **Local branch**: `${{ needs.check-merge.outputs.local_branch }}`
- **Latest upstream commit**: ${{ format('[`{0}`](https://github.com/prometheus/prometheus/commit/{0})', needs.check-merge.outputs.upstream_commit) }}
- **Latest upstream commit date**: ${{ needs.check-merge.outputs.commit_date }}
### Action Required
This **closed PR** serves as a placeholder that holds the branch and instructions for conflict resolution. Follow these steps to resolve conflicts and reopen this PR:
```bash
# 1. Fetch and check out the empty branch created by CI
git fetch origin
git checkout ${{ needs.check-merge.outputs.bot_branch }}
# 2. Fetch and merge the upstream commit to trigger conflicts
git remote add upstream https://github.com/prometheus/prometheus.git # Omit this step if you already have a remote configured for prometheus/prometheus.
git fetch upstream
git merge ${{ needs.check-merge.outputs.upstream_commit }} --no-edit
# 3. If conflicts occur:
# - Edit conflicted files and resolve conflicts
# - Look for conflict markers: <<<<<<< HEAD, =======, >>>>>>>
# - Remove conflict markers after resolving
# - Run: git add . && git merge --continue
# 4. Push your resolved merge (no force-push needed)
git push
# 5. Re-open the closed PR
# 6. Post the remerge diff as a comment for reviewers:
gh pr comment --body "## Merge Conflict Resolution
You can review how conflicts were resolved using:
\`\`\`bash
git show --remerge-diff
\`\`\`
<details>
<summary>Click to expand remerge diff output</summary>
\`\`\`diff
$(git show --remerge-diff)
\`\`\`
</details>"
```
commit-message: "Empty commit to create branch for conflict resolution"
branch: ${{ needs.check-merge.outputs.bot_branch }}
base: ${{ needs.check-merge.outputs.local_branch }}
delete-branch: false
draft: true
- name: Close PR by force-pushing to HEAD~1
run: |
# Force-push to the same commit as the base branch (removes the empty commit, leaving no commits in the PR).
# This closes the PR while keeping the branch and instructions as a placeholder
git push --force origin ${{needs.check-merge.outputs.local_branch}}:${{ needs.check-merge.outputs.bot_branch }}
- name: Send Slack notification for merge conflicts
uses: grafana/shared-workflows/actions/send-slack-message@7b628e7352c2dea057c565cc4fcd5564d5f396c0 #v1.0.0
with:
channel-id: C04AF91LPFX #mimir-ci-notifications
payload: |
{
"text": ":sadcomputer: *Merge conflicts detected in upstream prometheus merge* (prometheus/`${{ needs.check-merge.outputs.upstream_branch }}` -> mimir-prometheus/`${{ needs.check-merge.outputs.local_branch }}`)\n\n<!subteam^S05TQM9UAAF> check and resolve the conflicts in <${{ steps.create-conflict-pr.outputs.pull-request-url }}|the PR>."
}
handle-error:
runs-on: ubuntu-latest
needs: [check-merge, attempt-merge]
if: needs.attempt-merge.outputs.merge_result == 'error'
permissions:
id-token: write
steps:
- name: Send Slack notification for merge error
uses: grafana/shared-workflows/actions/send-slack-message@7b628e7352c2dea057c565cc4fcd5564d5f396c0 #v1.0.0
with:
channel-id: C04AF91LPFX #mimir-ci-notifications
payload: |
{
"text": ":sadcomputer: *Upstream prometheus merge failed* (prometheus/`${{ needs.check-merge.outputs.upstream_branch }}` -> mimir-prometheus/`${{ needs.check-merge.outputs.local_branch }}`)\n\n<!subteam^S05TQM9UAAF> please investigate the <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|workflow logs> and resolve manually."
}
- name: Mark workflow as failed
run: exit 1
create-pr:
runs-on: ubuntu-latest
needs: [check-merge, attempt-merge]
if: needs.attempt-merge.outputs.merge_result == 'success'
permissions:
contents: write
pull-requests: write
id-token: write
steps:
- name: Check out repository
uses: actions/checkout@v4
with:
ref: ${{ needs.check-merge.outputs.local_branch }}
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0
set-safe-directory: "*"
- name: Add prometheus/prometheus remote and perform merge
run: |
git remote add prometheus https://github.com/prometheus/prometheus.git
git fetch prometheus ${{ needs.check-merge.outputs.upstream_commit }}
# Configure git
git config user.name "mimir-github-bot[bot]"
git config user.email "mimir-github-bot[bot]@users.noreply.github.com"
# Perform the merge (we know it will succeed)
git merge ${{ needs.check-merge.outputs.upstream_commit }} --no-edit
# This job uses "mimir-github-bot" instead of "github-actions bot" (secrets.GITHUB_TOKEN)
# because any events triggered by the later don't spawn GitHub actions.
# Refer to https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication#using-the-github_token-in-a-workflow
- name: Retrieve GitHub App Credentials from Vault
id: get-secrets
uses: grafana/shared-workflows/actions/get-vault-secrets@28361cdb22223e5f1e34358c86c20908e7248760 # v1.1.0
with:
repo_secrets: |
APP_ID=mimir-github-bot:app_id
PRIVATE_KEY=mimir-github-bot:private_key
- name: Generate GitHub App Token
id: app-token
uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # v1.12.0
with:
app-id: ${{ env.APP_ID }}
private-key: ${{ env.PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
- name: Create Pull Request
id: create-pr
uses: peter-evans/create-pull-request@4e1beaa7521e8b457b572c090b25bd3db56bf1c5 # v5.0.3
with:
token: ${{ steps.app-token.outputs.token }}
title: "[${{ needs.check-merge.outputs.local_branch }}] Merge upstream prometheus/${{ needs.check-merge.outputs.upstream_branch }} to ${{ needs.check-merge.outputs.upstream_short }}"
body: |
## Merge from prometheus/prometheus
*This PR was automatically created by the [merge-upstream-prometheus workflow](https://github.com/grafana/mimir-prometheus/blob/main/.github/workflows/merge-upstream-prometheus.yml)*
### Details:
- **Upstream branch**: `${{ needs.check-merge.outputs.upstream_branch }}`
- **Local branch**: `${{ needs.check-merge.outputs.local_branch }}`
- **Latest upstream commit**: ${{ format('[`{0}`](https://github.com/prometheus/prometheus/commit/{0})', needs.check-merge.outputs.upstream_commit) }}
- **Latest upstream commit date**: ${{ needs.check-merge.outputs.commit_date }}
### Changes:
This PR merges the latest changes from the upstream prometheus/prometheus `${{ needs.check-merge.outputs.upstream_branch }}` branch.
commit-message: "Merge upstream prometheus/${{ needs.check-merge.outputs.upstream_branch }} (${{ needs.check-merge.outputs.upstream_short }})"
branch: ${{ needs.check-merge.outputs.bot_branch }}
base: ${{ needs.check-merge.outputs.local_branch }}
delete-branch: true
no-merge-needed:
runs-on: ubuntu-latest
needs: check-merge
if: needs.check-merge.outputs.merge_needed == 'false'
permissions:
contents: read
steps:
- name: No merge needed
run: |
echo "Repository is already up to date with upstream prometheus/${{ needs.check-merge.outputs.upstream_branch }}"