LemonCode host #392
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: LemonCode host | |
| on: | |
| workflow_dispatch: | |
| schedule: | |
| - cron: "23 * * * *" | |
| permissions: | |
| contents: write | |
| concurrency: | |
| group: lemoncode-host | |
| cancel-in-progress: false | |
| defaults: | |
| run: | |
| shell: bash | |
| jobs: | |
| sync: | |
| name: Sync and validate upstream | |
| runs-on: ubuntu-latest | |
| outputs: | |
| changed: ${{ steps.merge.outputs.changed }} | |
| sha: ${{ steps.meta.outputs.sha }} | |
| version: ${{ steps.meta.outputs.version }} | |
| steps: | |
| - name: Check out controlled fork | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: dev | |
| fetch-depth: 0 | |
| - name: Merge upstream | |
| id: merge | |
| run: | | |
| git remote add upstream https://github.com/anomalyco/opencode.git | |
| git fetch upstream dev | |
| if git merge-base --is-ancestor upstream/dev HEAD; then | |
| echo "changed=false" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| git config user.name "lemoncrow-sync[bot]" | |
| git config user.email "lemoncrow-sync@users.noreply.github.com" | |
| git merge --no-edit upstream/dev | |
| echo "changed=true" >> "$GITHUB_OUTPUT" | |
| - name: Set up Bun | |
| if: steps.merge.outputs.changed == 'true' | |
| uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 | |
| with: | |
| bun-version-file: package.json | |
| - name: Install dependencies | |
| if: steps.merge.outputs.changed == 'true' | |
| run: bun install --frozen-lockfile | |
| - name: Validate downstream controls | |
| if: steps.merge.outputs.changed == 'true' | |
| run: | | |
| bun --cwd packages/core test test/product.test.ts | |
| bun --cwd packages/core typecheck | |
| bun --cwd packages/tui typecheck | |
| bun --cwd packages/opencode typecheck | |
| - name: Push validated merge | |
| if: steps.merge.outputs.changed == 'true' | |
| run: git push origin HEAD:dev | |
| - name: Resolve build revision | |
| id: meta | |
| run: | | |
| echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" | |
| echo "version=$(python3 -c 'import json; print(json.load(open("packages/opencode/package.json"))["version"])')" >> "$GITHUB_OUTPUT" | |
| build: | |
| name: Build ${{ matrix.asset }} | |
| needs: sync | |
| if: needs.sync.outputs.changed == 'true' || github.event_name == 'workflow_dispatch' | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - runner: ubuntu-latest | |
| asset: linux-x64 | |
| - runner: ubuntu-24.04-arm | |
| asset: linux-arm64 | |
| - runner: macos-latest | |
| asset: darwin-arm64 | |
| - runner: macos-15-intel | |
| asset: darwin-x64 | |
| runs-on: ${{ matrix.runner }} | |
| steps: | |
| - name: Check out controlled fork revision | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ needs.sync.outputs.sha }} | |
| - name: Set up Bun | |
| uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 | |
| with: | |
| bun-version-file: package.json | |
| - name: Install dependencies | |
| run: bun install --frozen-lockfile | |
| - name: Build LemonCode | |
| working-directory: packages/opencode | |
| run: bun run script/build.ts --single --skip-embed-web-ui | |
| - name: Upload binary | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: lemoncode-${{ matrix.asset }} | |
| path: packages/opencode/dist/lemoncode-${{ matrix.asset }}/bin/lemoncode | |
| if-no-files-found: error | |
| release: | |
| name: Publish verified host release | |
| needs: [sync, build] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Download binaries | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: lemoncode-* | |
| path: artifacts | |
| - name: Package binaries and checksums | |
| run: | | |
| mkdir -p release | |
| for directory in artifacts/lemoncode-*; do | |
| asset="$(basename "$directory")" | |
| tar -C "$directory" -czf "release/${asset}.tar.gz" lemoncode | |
| sha256sum "release/${asset}.tar.gz" > "release/${asset}.tar.gz.sha256" | |
| done | |
| - name: Publish release | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| FORK_REPO: ${{ github.repository }} | |
| HOST_SHA: ${{ needs.sync.outputs.sha }} | |
| HOST_VERSION: ${{ needs.sync.outputs.version }} | |
| run: | | |
| short="${HOST_SHA:0:12}" | |
| tag="v${HOST_VERSION}-lemoncode.${short}" | |
| if gh release view "$tag" --repo "$FORK_REPO" >/dev/null 2>&1; then | |
| gh release upload "$tag" release/* --clobber --repo "$FORK_REPO" | |
| exit 0 | |
| fi | |
| gh release create "$tag" release/* \ | |
| --repo "$FORK_REPO" \ | |
| --target "$HOST_SHA" \ | |
| --latest \ | |
| --title "LemonCode ${HOST_VERSION} (${short})" \ | |
| --notes "Controlled LemonCode host built from upstream OpenCode ${HOST_VERSION}; downstream source and attribution remain in the fork." |