Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 131 additions & 0 deletions .github/rebase-upstream-prod-conflict.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# Manual Rebase Conflict Resolution Guide

This guide explains how to manually resolve rebase conflicts when the automated rebase workflow fails.

## Overview

The automated workflow attempts to rebase the `opensoft-prod` branch onto the upstream `production` branch. When conflicts occur, they must be resolved manually.

## Prerequisites

- Git installed locally
- Write access to the opensoft/opencode repository
- Familiarity with Git rebase and conflict resolution

## Steps to Resolve Conflicts

### 1. Clone the Repository (if not already done)

```bash
git clone https://github.com/opensoft/opencode.git
cd opencode
```

### 2. Add the Upstream Remote

```bash
git remote add upstream https://github.com/sst/opencode.git
```

If the remote already exists, you can skip this step or update it:

```bash
git remote set-url upstream https://github.com/sst/opencode.git
```

### 3. Fetch All Remotes

```bash
git fetch origin
git fetch upstream
```

### 4. Checkout the opensoft-prod Branch

```bash
git checkout opensoft-prod
```

### 5. Start the Rebase

```bash
git rebase upstream/production
```

### 6. Resolve Conflicts

When conflicts occur, Git will pause and show you which files have conflicts:

```
CONFLICT (content): Merge conflict in <filename>
```

For each conflicted file:

1. Open the file in your editor
2. Look for conflict markers:
```
<<<<<<< HEAD
(upstream/production changes)
=======
(your opensoft-prod changes)
>>>>>>> opensoft-prod
```
3. Edit the file to resolve the conflict, keeping the appropriate changes
4. Remove the conflict markers
5. Save the file

### 7. Mark Files as Resolved

After resolving conflicts in a file:

```bash
git add <filename>
```

### 8. Continue the Rebase

```bash
git rebase --continue
```

Repeat steps 6-8 for each conflict that occurs during the rebase.

### 9. Force Push to Update opensoft-prod

⚠️ **Warning**: This is a force push operation. Make sure you've resolved all conflicts correctly.

```bash
git push --force-with-lease origin opensoft-prod
```

Using `--force-with-lease` is safer than `--force` as it will fail if someone else has pushed changes since you last fetched.

## Aborting the Rebase

If you need to abort the rebase and start over:

```bash
git rebase --abort
```

This will return your branch to the state before the rebase started.

## Tips

- **Review changes carefully**: Use `git diff` to review changes before continuing
- **Test after resolution**: If possible, test the code after resolving conflicts
- **Ask for help**: If you're unsure about a conflict, consult with team members
- **Document complex resolutions**: If a conflict required non-obvious resolution, document it in the commit message

## Verification

After successfully pushing, verify the rebase:

1. Check the commit history: `git log --oneline -10`
2. Verify the branch has the expected upstream changes
3. Ensure any custom opensoft changes are preserved

## Re-running the Automated Workflow

After manually resolving and pushing, the automated workflow should succeed on its next run (or you can trigger it manually using workflow_dispatch).
170 changes: 170 additions & 0 deletions .github/workflows/rebase-upstream-prod.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
name: Rebase opensoft-prod onto upstream production

on:
schedule:
# Run every Sunday at 23:00 UTC (Sunday night)
- cron: "0 23 * * 0"
workflow_dispatch:

concurrency: ${{ github.workflow }}
jobs:
rebase:
runs-on: blacksmith-4vcpu-ubuntu-2404
permissions:
contents: write
issues: write
steps:
- name: Checkout opensoft-prod branch
uses: actions/checkout@v4
with:
ref: opensoft-prod
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: Add upstream remote
run: |
if ! git remote | grep -q '^upstream$'; then
git remote add upstream https://github.com/sst/opencode.git
fi
git remote -v

- name: Fetch upstream
run: |
git fetch upstream production

- name: Rebase onto upstream/production
id: rebase
run: |
echo "Attempting rebase of opensoft-prod onto upstream/production..."
if git rebase upstream/production; then
echo "result=success" >> $GITHUB_OUTPUT
echo "Rebase successful"
else
echo "result=conflict" >> $GITHUB_OUTPUT
echo "Rebase failed with conflicts"
git rebase --abort
exit 1
fi

- name: Force push to origin
if: steps.rebase.outputs.result == 'success'
run: |
echo "Pushing rebased opensoft-prod to origin..."
git push --force-with-lease origin opensoft-prod
echo "Successfully pushed rebased branch"

- name: Create issue on conflict
if: failure() && steps.rebase.outputs.result == 'conflict'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const path = require('path');

// Read the conflict resolution instructions
const instructionsPath = path.join(
process.env.GITHUB_WORKSPACE,
'.github/rebase-upstream-prod-conflict.md'
);
let instructions = '';
try {
instructions = fs.readFileSync(instructionsPath, 'utf8');
} catch (error) {
instructions = [
'See .github/rebase-upstream-prod-conflict.md',
'for manual resolution instructions.'
].join(' ');
}

const issueTitle = [
'🔄 Rebase Conflict: opensoft-prod onto',
'upstream/production',
`(${new Date().toISOString().split('T')[0]})`
].join(' ');
const issueBody = `## Automated Rebase Failed

The automated rebase of \`opensoft-prod\` onto \`upstream/production\` has encountered conflicts that require manual resolution.

**Workflow Run:** [#${context.runNumber}](${context.payload.repository.html_url}/actions/runs/${context.runId})

## What Happened

The GitHub Actions workflow attempted to:
1. Fetch the latest \`production\` branch from upstream (sst/opencode)
2. Rebase \`opensoft-prod\` onto \`upstream/production\`
3. The rebase encountered merge conflicts and was aborted

## Next Steps

A maintainer needs to manually resolve the conflicts and push the rebased branch. Please follow the instructions below:

---

${instructions}

---

## After Resolution

Once you've manually resolved and pushed the changes:
- [ ] Verify \`opensoft-prod\` is up to date with \`upstream/production\`
- [ ] Close this issue
- [ ] The next automated run should succeed
`.trim();

// Check if an issue already exists
const existingIssues = await github.rest.issues.listForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
labels: 'rebase-conflict',
per_page: 10
});

// Only create a new issue if one doesn't already exist
if (existingIssues.data.length === 0) {
const issue = await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: issueTitle,
body: issueBody,
labels: [
'rebase-conflict',
'maintenance',
'automated'
]
});

console.log(`Created issue #${issue.data.number}`);
} else {
const existingNum = existingIssues.data[0].number;
console.log(`Issue already exists: #${existingNum}`);

// Add a comment to the existing issue
const date = new Date().toISOString().split('T')[0];
const runUrl = [
context.payload.repository.html_url,
'/actions/runs/',
context.runId
].join('');
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: existingIssues.data[0].number,
body: [
`Another rebase conflict detected on ${date}.\n\n`,
`Workflow Run: [#${context.runNumber}](${runUrl})`
].join('')
});
}

- name: Notify on failure
if: failure() && steps.rebase.outputs.result != 'conflict'
run: |
echo "::error::Rebase workflow failed unexpectedly. Check logs."
exit 1
Loading