Skip to content

Commit 4de69c1

Browse files
author
IWWA
committed
ci: workflow diário que sincroniza iwwa com a release do upstream e publica o binário iwwacode
1 parent ae53163 commit 4de69c1

1 file changed

Lines changed: 163 additions & 0 deletions

File tree

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
# IWWA — sincroniza a branch `iwwa` com a última RELEASE estável do upstream sst/opencode,
2+
# rebaseando as modificações da IWWA por cima, buildando o binário `iwwacode` (Linux glibc x64)
3+
# e publicando-o como asset de uma release do fork.
4+
#
5+
# Por que polling (cron) e não o evento `release`? O `release` só dispara para releases do
6+
# PRÓPRIO repo; não dá pra ouvir a release de sst/opencode. Então checamos 1x/dia.
7+
#
8+
# Este workflow VIVE na branch default `dev` (de onde o agendamento dispara) mas OPERA sobre a
9+
# `iwwa` — assim ele não entra no patch da IWWA (mantém o diff em 3 arquivos = rebase barato).
10+
name: IWWA sync release
11+
12+
on:
13+
schedule:
14+
- cron: "23 6 * * *" # diário ~06:23 UTC
15+
workflow_dispatch:
16+
inputs:
17+
ref:
18+
description: "Tag do upstream (vazio = última release). Ex.: v1.17.11"
19+
required: false
20+
default: ""
21+
force:
22+
description: "Rebuildar mesmo se a release do fork já existir"
23+
type: boolean
24+
default: false
25+
26+
permissions:
27+
contents: write # push --force-with-lease na iwwa + criar release/tag no fork
28+
issues: write # abrir issue se o rebase conflitar
29+
30+
concurrency:
31+
group: iwwa-sync-release
32+
cancel-in-progress: false
33+
34+
env:
35+
UPSTREAM: sst/opencode
36+
IWWA_BRANCH: iwwa
37+
IWWA_MARKER: X-IWWA-Session # marcador que prova que o patch IWWA sobreviveu ao rebase
38+
39+
jobs:
40+
sync:
41+
runs-on: ubuntu-latest
42+
steps:
43+
- name: Descobrir a release alvo do upstream
44+
id: target
45+
env:
46+
GH_TOKEN: ${{ github.token }}
47+
run: |
48+
set -euo pipefail
49+
if [ -n "${{ inputs.ref }}" ]; then
50+
TAG="${{ inputs.ref }}"
51+
else
52+
TAG="$(gh release view --repo "$UPSTREAM" --json tagName -q .tagName)"
53+
fi
54+
[ -n "$TAG" ] || { echo "::error::não consegui resolver a tag de release do upstream"; exit 1; }
55+
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
56+
echo "rel=iwwacode-$TAG" >> "$GITHUB_OUTPUT"
57+
echo ">> release alvo: $TAG"
58+
59+
- name: Já temos essa release no fork?
60+
id: have
61+
env:
62+
GH_TOKEN: ${{ github.token }}
63+
run: |
64+
set -euo pipefail
65+
if [ "${{ inputs.force }}" = "true" ]; then
66+
echo "skip=false" >> "$GITHUB_OUTPUT"; echo ">> force=true, vai rebuildar"; exit 0
67+
fi
68+
if gh release view "${{ steps.target.outputs.rel }}" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
69+
echo "skip=true" >> "$GITHUB_OUTPUT"; echo ">> ${{ steps.target.outputs.rel }} já existe — nada a fazer"
70+
else
71+
echo "skip=false" >> "$GITHUB_OUTPUT"; echo ">> release nova, seguindo"
72+
fi
73+
74+
- name: Checkout da branch iwwa
75+
if: steps.have.outputs.skip == 'false'
76+
uses: actions/checkout@v4
77+
with:
78+
ref: ${{ env.IWWA_BRANCH }}
79+
fetch-depth: 0
80+
token: ${{ github.token }}
81+
82+
- name: Rebase da iwwa sobre a tag de release
83+
if: steps.have.outputs.skip == 'false'
84+
id: rebase
85+
run: |
86+
set -euo pipefail
87+
git config user.name "iwwa-bot"
88+
git config user.email "iwwa-bot@users.noreply.github.com"
89+
git remote add upstream "https://github.com/${UPSTREAM}.git" 2>/dev/null || true
90+
git fetch --no-tags upstream "refs/tags/${{ steps.target.outputs.tag }}:refs/tags/${{ steps.target.outputs.tag }}"
91+
if git rebase "${{ steps.target.outputs.tag }}"; then
92+
grep -q "$IWWA_MARKER" packages/core/src/session/runner/llm.ts \
93+
|| { echo "::error::marcador $IWWA_MARKER sumiu após o rebase"; exit 1; }
94+
echo ">> rebase ok, patch IWWA preservado"
95+
else
96+
git rebase --abort || true
97+
echo "conflict=true" >> "$GITHUB_OUTPUT"
98+
echo "::warning::rebase conflitou — upstream mexeu nas mesmas linhas do patch IWWA"
99+
exit 1
100+
fi
101+
102+
- name: Abrir issue se o rebase conflitar
103+
if: failure() && steps.rebase.outputs.conflict == 'true'
104+
env:
105+
GH_TOKEN: ${{ github.token }}
106+
run: |
107+
set -euo pipefail
108+
TITLE="Rebase automático falhou: iwwa sobre ${{ steps.target.outputs.tag }}"
109+
EXISTING="$(gh issue list --repo "$GITHUB_REPOSITORY" --state open \
110+
--search "in:title $TITLE" --json number -q '.[0].number' || true)"
111+
if [ -z "$EXISTING" ]; then
112+
gh issue create --repo "$GITHUB_REPOSITORY" --title "$TITLE" --body \
113+
"O rebase automático da branch \`iwwa\` sobre a release \`${{ steps.target.outputs.tag }}\` do upstream entrou em **conflito** (o upstream mexeu nas mesmas linhas do patch IWWA).
114+
115+
**Resolva manualmente** num clone de trabalho do fork:
116+
\`\`\`
117+
git fetch upstream tag ${{ steps.target.outputs.tag }}
118+
git checkout iwwa && git rebase ${{ steps.target.outputs.tag }}
119+
# resolva os conflitos mantendo a injeção X-IWWA-Session/X-IWWA-User e o branding IWWA CODE
120+
git push --force-with-lease origin iwwa
121+
\`\`\`
122+
Depois é só rodar o workflow de novo (ele rebuilda e publica a release)."
123+
else
124+
echo ">> issue #$EXISTING já aberta para essa tag"
125+
fi
126+
127+
- name: Push da iwwa rebaseada
128+
if: steps.have.outputs.skip == 'false'
129+
run: git push --force-with-lease origin "HEAD:${IWWA_BRANCH}"
130+
131+
- name: Setup bun
132+
if: steps.have.outputs.skip == 'false'
133+
uses: oven-sh/setup-bun@v2
134+
135+
- name: Build do binário iwwacode
136+
if: steps.have.outputs.skip == 'false'
137+
run: |
138+
set -euo pipefail
139+
bun install
140+
( cd packages/opencode && bun run build --single )
141+
BIN="$(ls packages/opencode/dist/opencode-linux-*/bin/opencode 2>/dev/null | grep -v musl | head -1 || true)"
142+
[ -n "$BIN" ] || { echo "::error::binário não encontrado em packages/opencode/dist/"; exit 1; }
143+
install -m 755 "$BIN" ./iwwacode
144+
./iwwacode --version || true
145+
shasum -a 256 ./iwwacode | tee iwwacode.sha256
146+
147+
- name: Publicar release com o binário
148+
if: steps.have.outputs.skip == 'false'
149+
env:
150+
GH_TOKEN: ${{ github.token }}
151+
run: |
152+
set -euo pipefail
153+
SHA="$(cut -d' ' -f1 iwwacode.sha256)"
154+
gh release create "${{ steps.target.outputs.rel }}" iwwacode iwwacode.sha256 \
155+
--repo "$GITHUB_REPOSITORY" \
156+
--target "$IWWA_BRANCH" \
157+
--title "iwwacode ${{ steps.target.outputs.tag }}" \
158+
--notes "Binário \`iwwacode\` (Linux glibc x64) buildado da branch \`iwwa\` rebaseada sobre o upstream \`${UPSTREAM}@${{ steps.target.outputs.tag }}\`.
159+
160+
\`\`\`
161+
sha256 $SHA
162+
\`\`\`
163+
Consumido pelo Dockerfile via \`deploy/fetch-iwwacode.sh\`."

0 commit comments

Comments
 (0)