From c0e9ad0aa7c15c1bebd2a348c4ba7026353f0794 Mon Sep 17 00:00:00 2001 From: Sam Morrow Date: Wed, 25 Jun 2025 12:07:17 +0200 Subject: [PATCH 1/3] add a new release workflow --- .github/workflows/docker-publish.yml | 4 +- .github/workflows/pr-base-check.yml | 55 ++++++++ .github/workflows/release.yml | 191 +++++++++++++++++++++++++++ CONTRIBUTING.md | 4 +- 4 files changed, 251 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/pr-base-check.yml create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 35ffc47db..cd2d923cb 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -9,11 +9,11 @@ on: schedule: - cron: "27 0 * * *" push: - branches: ["main"] + branches: ["main", "next"] # Publish semver tags as releases. tags: ["v*.*.*"] pull_request: - branches: ["main"] + branches: ["main", "next"] env: # Use docker.io for Docker Hub if empty diff --git a/.github/workflows/pr-base-check.yml b/.github/workflows/pr-base-check.yml new file mode 100644 index 000000000..6f48205ca --- /dev/null +++ b/.github/workflows/pr-base-check.yml @@ -0,0 +1,55 @@ +name: PR Base Branch Check + +on: + pull_request: + types: [opened, edited, synchronize] + branches: + - main + +permissions: + pull-requests: write + contents: read + +jobs: + check-base-branch: + runs-on: ubuntu-latest + if: github.event.pull_request.base.ref == 'main' + + steps: + - name: Comment on PR + uses: actions/github-script@v7 + with: + script: | + const message = `👋 Hi there! + + It looks like this PR is targeting the \`main\` branch. To help maintain our development workflow, please change the base reference to \`next\` instead. + + __If this is a bug fix that requires a patch release __ (e.g., a critical bug that needs to be fixed before the next release)__, please leave the base branch as \`main\`.__ + + You can change this by: + 1. Clicking the "Edit" button next to the PR title + 2. Changing the base branch from \`main\` to \`next\` + 3. Clicking "Update pull request" + + Thanks for your contribution! 🚀`; + + // Check if we've already commented + const comments = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + }); + + const botComment = comments.data.find(comment => + comment.user.type === 'Bot' && + comment.body.includes('please change the base reference to') + ); + + if (!botComment) { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: message + }); + } diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..0c909dcfd --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,191 @@ +name: Release + +on: + workflow_dispatch: + inputs: + tag: + description: 'Release tag (e.g., v0.0.0)' + required: true + default: 'v0.0.0' + type: string + confirm: + description: 'Type "CONFIRM" to proceed with the release' + required: true + type: string + +permissions: + contents: write + pull-requests: write + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - name: Validate confirmation + if: ${{ github.event.inputs.confirm != 'CONFIRM' }} + run: | + echo "::error::You must type 'CONFIRM' to proceed with the release" + exit 1 + + - name: Validate tag format + run: | + TAG="${{ github.event.inputs.tag }}" + if [[ ! $TAG =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-.*)?$ ]]; then + echo "::error::Tag must be in format vX.Y.Z or vX.Y.Z-suffix (e.g., v1.0.0 or v1.0.0-rc1)" + exit 1 + fi + + release: + needs: validate + runs-on: ubuntu-latest + outputs: + pr-number: ${{ steps.create-pr.outputs.pr-number }} + pr-url: ${{ steps.create-pr.outputs.pr-url }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Configure Git + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + - name: Switch to next branch + run: | + git checkout next + git pull origin next + + - name: Rebase next with main + id: rebase + run: | + echo "Attempting to rebase next with main..." + if git rebase origin/main; then + echo "✅ Rebase successful" + echo "rebase-success=true" >> $GITHUB_OUTPUT + else + echo "::error::❌ Rebase failed due to conflicts. Please resolve conflicts manually and try again." + echo "Conflicts detected in the following files:" + git status --porcelain | grep "^UU\|^AA\|^DD" || true + echo "rebase-success=false" >> $GITHUB_OUTPUT + exit 1 + fi + + - name: Check if tag already exists + run: | + TAG="${{ github.event.inputs.tag }}" + if git tag -l | grep -q "^${TAG}$"; then + echo "::error::Tag ${TAG} already exists" + exit 1 + fi + if git ls-remote --tags origin | grep -q "refs/tags/${TAG}$"; then + echo "::error::Tag ${TAG} already exists on remote" + exit 1 + fi + + - name: Tag the release + run: | + TAG="${{ github.event.inputs.tag }}" + git tag -a "${TAG}" -m "Release ${TAG}" + echo "✅ Created tag ${TAG}" + + - name: Create Pull Request + id: create-pr + run: | + TAG="${{ github.event.inputs.tag }}" + + # Create PR from next to main + PR_RESPONSE=$(gh pr create \ + --base main \ + --head next \ + --title "Release ${TAG}" \ + --body "This PR contains the changes for release ${TAG}. + + **Release checklist:** + - [ ] Review the changes + - [ ] Ensure all tests pass + - [ ] Verify the release notes in the draft release + - [ ] Merge this PR after the release is published + + Created by the automated release workflow." \ + --json number,url) + + PR_NUMBER=$(echo "$PR_RESPONSE" | jq -r '.number') + PR_URL=$(echo "$PR_RESPONSE" | jq -r '.url') + + echo "pr-number=${PR_NUMBER}" >> $GITHUB_OUTPUT + echo "pr-url=${PR_URL}" >> $GITHUB_OUTPUT + echo "✅ Created PR #${PR_NUMBER}: ${PR_URL}" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Push tag + run: | + TAG="${{ github.event.inputs.tag }}" + git push origin "${TAG}" + echo "✅ Pushed tag ${TAG}" + + - name: Wait for release to be created + run: | + TAG="${{ github.event.inputs.tag }}" + echo "Waiting for GitHub to create the draft release..." + + # Wait up to 2 minutes for the release to appear + for i in {1..24}; do + if gh release view "${TAG}" >/dev/null 2>&1; then + echo "✅ Draft release created" + break + fi + echo "Waiting for release to be created... (${i}/24)" + sleep 5 + done + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + summary: + needs: [validate, release] + runs-on: ubuntu-latest + if: always() && needs.release.result == 'success' + + steps: + - name: Release Summary + run: | + TAG="${{ github.event.inputs.tag }}" + PR_URL="${{ needs.release.outputs.pr-url }}" + + echo "## 🎉 Release $TAG has been initiated!" + echo "" + echo "### Next steps:" + echo "1. 📋 Check https://github.com/${{ github.repository }}/releases for the draft release to show up" + echo "2. ✏️ Edit the new release, delete the existing notes and click the auto-generate button GitHub provides" + echo "3. ✨ Add a section at the top calling out the main features" + echo "4. 🚀 Publish the release" + echo "5. 🔀 Merge the pull request into main: ${PR_URL}" + echo "6. Post message in #gh-mcp-releases channel in Slack and then share to the other mcp channels" + echo "" + echo "### Resources:" + echo "- 📦 Draft Release: https://github.com/${{ github.repository }}/releases/tag/$TAG" + echo "- 🔄 Pull Request: ${PR_URL}" + echo "" + echo "The release process is now ready for your review and completion!" + + # Also output as job summary + cat << EOF >> $GITHUB_STEP_SUMMARY + ## 🎉 Release $TAG has been initiated! + + ### Next steps: + 1. 📋 Check [releases page](https://github.com/${{ github.repository }}/releases) for the draft release to show up + 2. ✏️ Edit the new release, delete the existing notes and click the auto-generate button GitHub provides + 3. ✨ Add a section at the top calling out the main features + 4. 🚀 Publish the release + 5. 🔀 Merge the pull request into main: [PR #${{ needs.release.outputs.pr-number }}](${PR_URL}) + + ### Resources: + - 📦 [Draft Release](https://github.com/${{ github.repository }}/releases/tag/$TAG) + - 🔄 [Pull Request](${PR_URL}) + + The release process is now ready for your review and completion! + EOF diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 11d63a389..6fa9c2ebe 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -19,12 +19,14 @@ These are one time installations required to be able to test your changes locall ## Submitting a pull request +> **Important**: Please open your pull request against the `next` branch, not `main`. The `next` branch is where we integrate new features and changes before they are merged to `main`. + 1. [Fork][fork] and clone the repository 1. Make sure the tests pass on your machine: `go test -v ./...` 1. Make sure linter passes on your machine: `golangci-lint run` 1. Create a new branch: `git checkout -b my-branch-name` 1. Make your change, add tests, and make sure the tests and linter still pass -1. Push to your fork and [submit a pull request][pr] +1. Push to your fork and [submit a pull request][pr] targeting the `next` branch 1. Pat yourself on the back and wait for your pull request to be reviewed and merged. Here are a few things you can do that will increase the likelihood of your pull request being accepted: From d94992cd30695069ca281b913bfb7b58cd418178 Mon Sep 17 00:00:00 2001 From: Sam Morrow Date: Thu, 26 Jun 2025 16:45:20 +0200 Subject: [PATCH 2/3] improve release.yml to ensure that the ref is up-to-date --- .github/workflows/release.yml | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0c909dcfd..72a9407eb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -59,20 +59,33 @@ jobs: git checkout next git pull origin next - - name: Rebase next with main - id: rebase + - name: Check next branch is up-to-date with main + id: branch-check run: | - echo "Attempting to rebase next with main..." - if git rebase origin/main; then - echo "✅ Rebase successful" - echo "rebase-success=true" >> $GITHUB_OUTPUT - else - echo "::error::❌ Rebase failed due to conflicts. Please resolve conflicts manually and try again." - echo "Conflicts detected in the following files:" - git status --porcelain | grep "^UU\|^AA\|^DD" || true - echo "rebase-success=false" >> $GITHUB_OUTPUT + echo "Checking if next branch is up-to-date with main..." + + # Fetch latest main branch + git fetch origin main + + # Check if next is behind main + BEHIND_COUNT=$(git rev-list --count next..origin/main) + AHEAD_COUNT=$(git rev-list --count origin/main..next) + + echo "Next branch is ${AHEAD_COUNT} commits ahead of main" + echo "Next branch is ${BEHIND_COUNT} commits behind main" + + if [ "$BEHIND_COUNT" -gt 0 ]; then + echo "::error::❌ Next branch is ${BEHIND_COUNT} commits behind main. Please update next branch with the latest changes from main before creating a release." + echo "To fix this, run: git checkout next && git merge main" exit 1 fi + + if [ "$AHEAD_COUNT" -eq 0 ]; then + echo "::warning::⚠️ Next branch has no new commits compared to main. Are you sure you want to create a release?" + fi + + echo "✅ Next branch is up-to-date with main (${AHEAD_COUNT} commits ahead)" + echo "branch-check-success=true" >> $GITHUB_OUTPUT - name: Check if tag already exists run: | From cc2f6477ef604549ac173fd76c42ee19422fc930 Mon Sep 17 00:00:00 2001 From: Sam Morrow Date: Thu, 26 Jun 2025 17:00:45 +0200 Subject: [PATCH 3/3] add sync workflow --- .github/workflows/sync-next-branch.yml | 166 +++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 .github/workflows/sync-next-branch.yml diff --git a/.github/workflows/sync-next-branch.yml b/.github/workflows/sync-next-branch.yml new file mode 100644 index 000000000..863613021 --- /dev/null +++ b/.github/workflows/sync-next-branch.yml @@ -0,0 +1,166 @@ +name: Sync Next Branch + +on: + schedule: + # Run daily at 9:00 AM UTC (6:00 AM EST, 3:00 AM PST) + - cron: '0 9 * * *' + workflow_dispatch: + # Allow manual triggering + +permissions: + contents: write + pull-requests: write + +jobs: + check-and-sync: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Configure Git + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + - name: Check branch status + id: branch-status + run: | + echo "Checking if next branch is up-to-date with main..." + + # Fetch latest branches + git fetch origin main + git fetch origin next + + # Check if next is behind main + BEHIND_COUNT=$(git rev-list --count origin/next..origin/main) + AHEAD_COUNT=$(git rev-list --count origin/main..origin/next) + + echo "Next branch is ${AHEAD_COUNT} commits ahead of main" + echo "Next branch is ${BEHIND_COUNT} commits behind main" + + echo "behind-count=${BEHIND_COUNT}" >> $GITHUB_OUTPUT + echo "ahead-count=${AHEAD_COUNT}" >> $GITHUB_OUTPUT + + if [ "$BEHIND_COUNT" -gt 0 ]; then + echo "needs-sync=true" >> $GITHUB_OUTPUT + echo "🔄 Next branch needs to be synced (${BEHIND_COUNT} commits behind)" + else + echo "needs-sync=false" >> $GITHUB_OUTPUT + echo "✅ Next branch is up-to-date with main" + fi + + - name: Check for existing sync PR + id: existing-pr + if: steps.branch-status.outputs.needs-sync == 'true' + run: | + # Check if there's already an open PR from main to next for syncing + EXISTING_PR=$(gh pr list \ + --base next \ + --head main \ + --state open \ + --json number,title \ + --jq '.[] | select(.title | test("^(Sync|Update) next branch")) | .number') + + if [ -n "$EXISTING_PR" ]; then + echo "existing-pr=${EXISTING_PR}" >> $GITHUB_OUTPUT + echo "⚠️ Sync PR already exists: #${EXISTING_PR}" + echo "has-existing-pr=true" >> $GITHUB_OUTPUT + else + echo "has-existing-pr=false" >> $GITHUB_OUTPUT + echo "No existing sync PR found" + fi + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Create sync PR + id: create-sync-pr + if: steps.branch-status.outputs.needs-sync == 'true' && steps.existing-pr.outputs.has-existing-pr == 'false' + run: | + BEHIND_COUNT="${{ steps.branch-status.outputs.behind-count }}" + AHEAD_COUNT="${{ steps.branch-status.outputs.ahead-count }}" + + # Create PR from main to next + PR_RESPONSE=$(gh pr create \ + --base next \ + --head main \ + --title "Sync next branch with main" \ + --body "## 🔄 Automated Branch Sync + + This PR syncs the \`next\` branch with the latest changes from \`main\`. + + ### Status: + - **Behind main**: ${BEHIND_COUNT} commits + - **Ahead of main**: ${AHEAD_COUNT} commits + + ### What to do: + 1. 🔍 Review the changes in this PR + 2. ✅ Ensure all checks pass + 3. 🔀 Merge this PR to sync the \`next\` branch + 4. 🗑️ The \`next\` branch will then be ready for new development + + > **Note**: This PR was automatically created by the daily branch sync workflow. + > If you have any concerns about these changes, please review them carefully before merging." \ + --label "automated" \ + --label "sync" \ + --json number,url) + + PR_NUMBER=$(echo "$PR_RESPONSE" | jq -r '.number') + PR_URL=$(echo "$PR_RESPONSE" | jq -r '.url') + + echo "pr-number=${PR_NUMBER}" >> $GITHUB_OUTPUT + echo "pr-url=${PR_URL}" >> $GITHUB_OUTPUT + + echo "✅ Created sync PR #${PR_NUMBER}: ${PR_URL}" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Job Summary + if: always() + run: | + BEHIND_COUNT="${{ steps.branch-status.outputs.behind-count }}" + AHEAD_COUNT="${{ steps.branch-status.outputs.ahead-count }}" + NEEDS_SYNC="${{ steps.branch-status.outputs.needs-sync }}" + HAS_EXISTING_PR="${{ steps.existing-pr.outputs.has-existing-pr }}" + EXISTING_PR="${{ steps.existing-pr.outputs.existing-pr }}" + NEW_PR_URL="${{ steps.create-sync-pr.outputs.pr-url }}" + NEW_PR_NUMBER="${{ steps.create-sync-pr.outputs.pr-number }}" + + cat << EOF >> $GITHUB_STEP_SUMMARY + # 🔄 Branch Sync Status + + ## Current Status: + - **Next branch**: ${AHEAD_COUNT} commits ahead, ${BEHIND_COUNT} commits behind main + - **Needs sync**: ${NEEDS_SYNC} + + EOF + + if [ "$NEEDS_SYNC" = "true" ]; then + if [ "$HAS_EXISTING_PR" = "true" ]; then + cat << EOF >> $GITHUB_STEP_SUMMARY + ## ⚠️ Action Required: + There is already an existing sync PR: [#${EXISTING_PR}](https://github.com/${{ github.repository }}/pull/${EXISTING_PR}) + + Please review and merge the existing PR to sync the next branch. + EOF + elif [ -n "$NEW_PR_NUMBER" ]; then + cat << EOF >> $GITHUB_STEP_SUMMARY + ## ✅ Action Taken: + Created a new sync PR: [#${NEW_PR_NUMBER}](${NEW_PR_URL}) + + **Next steps:** + 1. Review the changes in the PR + 2. Ensure all checks pass + 3. Merge the PR to sync the next branch + EOF + fi + else + cat << EOF >> $GITHUB_STEP_SUMMARY + ## ✅ All Good! + The next branch is up-to-date with main. No action needed. + EOF + fi pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy