welan release #8
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: welan release | |
| # 第一步,配置自己的上游仓库地址。 | |
| # 第二步,根据 CI 输入的 version 号,确保它是一个上游的 tag。如果输入的 version 号为空,那么自动从上游的 tag 里面获取最新的 tag 作为 version 号来工作。 | |
| # 第三步:获取上游对应版本的代码,在当前仓库的缺省分支上进行 Rebase。如果 Rebase 失败,需要把具体的冲突代码和文件打印成日志,然后报错退出。 | |
| # 第四步,我们运行 run 命令相关模块测试,确保 rebase 后行为正确且无边际回归。 | |
| # 第五步,我们分别构建 macOS、ARM 的 Linux、x86 的 Linux、ARM 的二进制。 | |
| # 第 6 步,我们将缺省分支推送到远端,并且新建一个 release version 的新分支推送到远端进行留存。 | |
| # 那第 7 步的话,我们发布一个 version 对应的 release。 | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: "Upstream release tag. Defaults to latest upstream tag." | |
| required: false | |
| type: string | |
| concurrency: | |
| group: welan-release | |
| cancel-in-progress: false | |
| permissions: | |
| contents: write | |
| env: | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true | |
| GH_TOKEN: ${{ github.token }} | |
| jobs: | |
| release: | |
| name: sync, validate, build, release | |
| runs-on: ubuntu-24.04 | |
| defaults: | |
| run: | |
| shell: bash | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ github.token }} | |
| - name: Configure git identity | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| - name: Configure upstream remote | |
| run: | | |
| if git remote get-url upstream >/dev/null 2>&1; then | |
| git remote set-url upstream https://github.com/anomalyco/opencode.git | |
| else | |
| git remote add upstream https://github.com/anomalyco/opencode.git | |
| fi | |
| - name: Resolve upstream tag | |
| run: | | |
| version="${{ inputs.version }}" | |
| if [ -z "$version" ]; then | |
| remote_tags="$(git ls-remote --tags --sort=-v:refname upstream 'refs/tags/v[0-9]*')" | |
| version="$(printf '%s\n' "$remote_tags" | awk 'index($2, "^{}") == 0 { sub("refs/tags/", "", $2); print $2; exit }')" | |
| fi | |
| if [ -z "$version" ]; then | |
| echo "No upstream tag found" | |
| exit 1 | |
| fi | |
| build_version="${version#v}" | |
| echo "Using upstream tag: $version" | |
| echo "Using build version: $build_version" | |
| echo "RELEASE_TAG=$version" >> "$GITHUB_ENV" | |
| echo "BUILD_VERSION=$build_version" >> "$GITHUB_ENV" | |
| - name: Fetch branches and tags | |
| run: | | |
| git fetch origin welan:refs/remotes/origin/welan --tags | |
| git fetch upstream "refs/tags/$RELEASE_TAG:refs/tags/$RELEASE_TAG" | |
| git rev-parse --verify "refs/tags/$RELEASE_TAG^{commit}" >/dev/null | |
| - name: Prepare dev from upstream tag | |
| run: | | |
| git checkout -B dev "$RELEASE_TAG" | |
| - name: Rebase welan onto dev | |
| id: rebase | |
| continue-on-error: true | |
| run: | | |
| git checkout -B welan origin/welan | |
| git rebase dev | |
| - name: Print rebase conflict details | |
| if: steps.rebase.outcome == 'failure' | |
| run: | | |
| conflicted_files="$(git diff --name-only --diff-filter=U || true)" | |
| upstream_tag="$(git rev-parse "$RELEASE_TAG")" | |
| origin_welan="$(git rev-parse origin/welan)" | |
| current_head="$(git rev-parse HEAD)" | |
| echo "::error::welan release $RELEASE_TAG hit a rebase conflict" | |
| echo "Version: $RELEASE_TAG" | |
| echo "Run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" | |
| echo "Upstream tag: $RELEASE_TAG" | |
| echo "Upstream tag SHA: ${upstream_tag}" | |
| echo "origin/welan: ${origin_welan}" | |
| echo "Current HEAD during conflict: ${current_head}" | |
| echo | |
| echo "Conflicted files:" | |
| printf '%s\n' "$conflicted_files" | |
| echo | |
| echo "Git status:" | |
| git status --short | |
| echo | |
| echo "Combined conflict diff:" | |
| git diff --cc || true | |
| echo | |
| echo "Conflicted file contents:" | |
| while IFS= read -r file; do | |
| [ -n "$file" ] || continue | |
| echo "::group::${file}" | |
| if [ -f "$file" ] && grep -Iq . "$file"; then | |
| cat "$file" | |
| else | |
| echo "Binary or missing conflicted file: $file" | |
| fi | |
| echo "::endgroup::" | |
| done <<< "$conflicted_files" | |
| git rebase --abort || true | |
| exit 1 | |
| - name: Setup Node | |
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 | |
| with: | |
| node-version: "24" | |
| - name: Setup Bun | |
| uses: ./.github/actions/setup-bun | |
| - name: Run run command module tests | |
| working-directory: packages/opencode | |
| timeout-minutes: 25 | |
| run: | | |
| bun test --timeout 60000 test/cli/run/ --path-ignore-patterns 'run-process*.test.ts' | |
| bun test --timeout 60000 --max-concurrency=1 test/cli/run/run-process-limit.test.ts | |
| bun test --timeout 60000 --max-concurrency=1 test/cli/run/run-process.test.ts | |
| env: | |
| OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER: "false" | |
| - name: Build CLI binaries | |
| run: OPENCODE_VERSION="$BUILD_VERSION" ./packages/opencode/script/build.ts | |
| - name: Package selected release assets | |
| run: | | |
| asset_dir="/tmp/welan-release-assets" | |
| rm -rf "$asset_dir" | |
| mkdir -p "$asset_dir" | |
| test -d packages/opencode/dist/opencode-darwin-arm64/bin | |
| test -d packages/opencode/dist/opencode-linux-arm64/bin | |
| test -d packages/opencode/dist/opencode-linux-x64/bin | |
| ( | |
| cd packages/opencode/dist/opencode-darwin-arm64/bin | |
| zip -r "$asset_dir/opencode-darwin-arm64.zip" . | |
| ) | |
| ( | |
| cd packages/opencode/dist/opencode-linux-arm64/bin | |
| tar -czf "$asset_dir/opencode-linux-arm64.tar.gz" . | |
| ) | |
| ( | |
| cd packages/opencode/dist/opencode-linux-x64/bin | |
| tar -czf "$asset_dir/opencode-linux-x64.tar.gz" . | |
| ) | |
| ls -lh "$asset_dir" | |
| - name: Push rebased welan | |
| run: git push origin HEAD:welan --force-with-lease | |
| - name: Push release archive branch | |
| run: | | |
| release_branch="release/$RELEASE_TAG" | |
| git checkout -B "$release_branch" | |
| git push origin "$release_branch" --force-with-lease | |
| - name: Replace GitHub release | |
| run: | | |
| tag="$RELEASE_TAG" | |
| target="$(git rev-parse HEAD)" | |
| if gh release view "$tag" --repo "${{ github.repository }}" >/dev/null 2>&1; then | |
| gh release delete "$tag" --repo "${{ github.repository }}" --yes | |
| fi | |
| if git ls-remote --exit-code --tags origin "refs/tags/$tag" >/dev/null 2>&1; then | |
| git push origin ":refs/tags/$tag" | |
| fi | |
| git tag -f "$tag" "$target" | |
| git push origin "refs/tags/$tag" | |
| gh release create "$tag" \ | |
| /tmp/welan-release-assets/opencode-darwin-arm64.zip \ | |
| /tmp/welan-release-assets/opencode-linux-arm64.tar.gz \ | |
| /tmp/welan-release-assets/opencode-linux-x64.tar.gz \ | |
| --repo "${{ github.repository }}" \ | |
| --target "$target" \ | |
| --title "$tag" \ | |
| --notes "Fork release built from welan at ${target}." |