Skip to content

ci: add pipeline for iii-lsp#22

Merged
guibeira merged 1 commit intomainfrom
pipeline-release-lsp-binary
Apr 9, 2026
Merged

ci: add pipeline for iii-lsp#22
guibeira merged 1 commit intomainfrom
pipeline-release-lsp-binary

Conversation

@guibeira
Copy link
Copy Markdown
Collaborator

@guibeira guibeira commented Apr 9, 2026

Summary by CodeRabbit

  • Chores
    • Automated release process for iii-lsp binary with support for tag-based triggering, dry-run releases, and prerelease versioning.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 9, 2026

📝 Walkthrough

Walkthrough

Adds a new GitHub Actions workflow file that automates the release process for the iii-lsp Rust binary. The workflow triggers on tag pushes matching iii-lsp/v* or manual dispatch, extracts version metadata from tags, optionally creates GitHub releases, and invokes a reusable Rust binary build workflow to compile and release the binary.

Changes

Cohort / File(s) Summary
Release Workflow
.github/workflows/release-lsp-binary.yml
Introduces a new GitHub Actions workflow with setup job to parse release tags (including prerelease and dry-run variants), create-release job to generate GitHub releases via softprops/action-gh-release, and binary-build job that delegates to reusable _rust-binary.yml workflow for compilation and artifact management.

Possibly related PRs

Poem

🐰 A binary goes forth with a tag and a name,
Through workflows and jobs, it finds its fame,
From Rust code to release, a smooth journey flow,
The LSP spreads wide wherever we go! 🚀

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'ci: add pipeline for iii-lsp' clearly and concisely describes the main change: adding a CI/CD pipeline for the iii-lsp component, which is exactly what the new GitHub Actions workflow file accomplishes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch pipeline-release-lsp-binary

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
.github/workflows/release-lsp-binary.yml (1)

81-84: Remove the checkout step—it's unnecessary for creating releases with tag_name and generate_release_notes.

The create-release job calls only softprops/action-gh-release@v2 with tag_name and generate_release_notes, which do not require a checked-out repository. The action accesses these via the GitHub Releases API, not the workspace. Removing checkout reduces runner time and limits token exposure.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/release-lsp-binary.yml around lines 81 - 84, Remove the
unnecessary checkout step (the action usage "actions/checkout@v4" block) from
the create-release job so the workflow relies solely on
softprops/action-gh-release@v2 with tag_name and generate_release_notes; locate
the job that invokes "softprops/action-gh-release@v2" and delete the "uses:
actions/checkout@v4" step (including its with: token) to reduce runner time and
token exposure while leaving the release action and its inputs intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/release-lsp-binary.yml:
- Around line 35-60: The workflow currently accepts arbitrary manual input in
the Resolve tag step (TAG in steps.resolve) and then parameter-expands away the
prefix in Extract metadata (steps.meta) without validating format, and later
passes the tag to softprops/action-gh-release@v2 without setting
target_commitish; fix by validating the resolved tag in the Resolve step (ensure
it matches the expected pattern like
^iii-lsp/v[0-9]+\.[0-9]+\.[0-9]+(?:-[a-z]+\.[0-9]+| -dry-run\.[0-9]+)?$ or at
minimum starts with "iii-lsp/v" and a semver-like version) and fail the job
early on invalid input, only allow stripping the "iii-lsp/v" prefix in Extract
metadata after validation (use steps.resolve.outputs.tag), and set the release
action's target_commitish to a deterministic ref (use github.sha for
manual_dispatch or github.ref for push events) when calling
softprops/action-gh-release@v2 so malformed or non-existent tags cannot create
releases from the default branch.
- Around line 17-19: The concurrency group currently uses github.ref (group:
release-iii-lsp-${{ github.ref }}) which resolves to branches for
workflow_dispatch; change it to key off the release tag instead by using the
release tag fallback expression, e.g. set group to release-iii-lsp-${{
github.event.release.tag_name || github.ref_name }}, so the concurrency group is
derived from the actual release tag (reference the concurrency group line and
the github.event.release.tag_name / github.ref_name symbols).

---

Nitpick comments:
In @.github/workflows/release-lsp-binary.yml:
- Around line 81-84: Remove the unnecessary checkout step (the action usage
"actions/checkout@v4" block) from the create-release job so the workflow relies
solely on softprops/action-gh-release@v2 with tag_name and
generate_release_notes; locate the job that invokes
"softprops/action-gh-release@v2" and delete the "uses: actions/checkout@v4" step
(including its with: token) to reduce runner time and token exposure while
leaving the release action and its inputs intact.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a873bcd6-44fa-42a3-bfaf-2abe3217ac18

📥 Commits

Reviewing files that changed from the base of the PR and between c2fbb17 and 3ac8165.

📒 Files selected for processing (1)
  • .github/workflows/release-lsp-binary.yml

Comment on lines +17 to +19
concurrency:
group: release-iii-lsp-${{ github.ref }}
cancel-in-progress: false
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In GitHub Actions, for top-level concurrency.group, is inputsavailable onworkflow_dispatch, and what does github.refresolve to onpushvsworkflow_dispatch?

💡 Result:

  • Is inputs available in a top-level concurrency.group on workflow_dispatch?
    Yes. The workflow-level concurrency key supports expressions using the github, inputs, and vars contexts, and the inputs context is available for workflows triggered by workflow_dispatch. [1]

  • What does github.ref resolve to?

    • On push: github.ref / GITHUB_REF is the updated ref that was pushed (branch or tag), e.g. refs/heads/main or refs/tags/v1.2.3. [2]
    • On workflow_dispatch: github.ref / GITHUB_REF is the branch or tag that received the dispatch (the ref you selected in the UI or passed as ref via the API/CLI). [3]

Sources
[1] GitHub Docs – Context availability table; concurrency supports github, inputs, vars, and inputs is available for workflow_dispatch workflows. (docs.github.com)
[2] GitHub Docs – push event: GITHUB_REF is the “Updated ref”. (docs.github.com)
[3] GitHub Docs – workflow_dispatch event: GITHUB_REF is “Branch or tag that received dispatch”. (docs.github.com)

Citations:


Use the release tag in the concurrency key instead of the workflow ref.

Line 18 keys concurrency by github.ref. On workflow_dispatch, this resolves to the branch from which the dispatch was triggered (e.g., refs/heads/main), not the release tag. The same release tag can therefore run under different concurrency groups when triggered via workflow_dispatch vs. a direct tag push, allowing concurrent execution instead of serialization.

Proposed fix
 concurrency:
-  group: release-iii-lsp-${{ github.ref }}
+  group: release-iii-lsp-${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }}
   cancel-in-progress: false
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
concurrency:
group: release-iii-lsp-${{ github.ref }}
cancel-in-progress: false
concurrency:
group: release-iii-lsp-${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }}
cancel-in-progress: false
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/release-lsp-binary.yml around lines 17 - 19, The
concurrency group currently uses github.ref (group: release-iii-lsp-${{
github.ref }}) which resolves to branches for workflow_dispatch; change it to
key off the release tag instead by using the release tag fallback expression,
e.g. set group to release-iii-lsp-${{ github.event.release.tag_name ||
github.ref_name }}, so the concurrency group is derived from the actual release
tag (reference the concurrency group line and the github.event.release.tag_name
/ github.ref_name symbols).

Comment on lines +35 to +60
- name: Resolve tag
id: resolve
run: |
TAG="${{ inputs.tag || github.ref_name }}"
echo "tag=$TAG" >> "$GITHUB_OUTPUT"

- name: Extract metadata from tag
id: meta
env:
TAG: ${{ steps.resolve.outputs.tag }}
run: |
VERSION="${TAG#iii-lsp/v}"

if [[ "$VERSION" =~ -dry-run\.[0-9]+$ ]]; then
echo "dry_run=true" >> "$GITHUB_OUTPUT"
echo "is_prerelease=true" >> "$GITHUB_OUTPUT"
elif [[ "$VERSION" =~ -([a-z]+)\.[0-9]+$ ]]; then
echo "dry_run=false" >> "$GITHUB_OUTPUT"
echo "is_prerelease=true" >> "$GITHUB_OUTPUT"
else
echo "dry_run=false" >> "$GITHUB_OUTPUT"
echo "is_prerelease=false" >> "$GITHUB_OUTPUT"
fi

echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "::notice::iii-lsp release -- tag=$TAG version=$VERSION"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

For softprops/action-gh-release@v2, what happens when tag_name does not already exist? Does it create the tag from the workflow commit?

💡 Result:

If you pass a tag_name that doesn’t already exist, softprops/action-gh-release@v2 will still create the release: it calls GitHub’s “Create a release” API, where tag_name may be an existing tag or a new one, and target_commitish specifies what commit/branch the new tag is created from (and is ignored if the tag already exists). [1]

So it does not automatically create the tag from the workflow run’s commit unless you explicitly set:

  • target_commitish: ${{ github.sha }}

Otherwise, the tag is created from the repo’s default branch by default. [2]

Sources:
[1] GitHub REST API “Create a release” parameters (tag_name, target_commitish) https://docs.github.com/en/rest/releases/releases
[2] softprops/action-gh-release@v2 README (tag_name default, target_commitish behavior/default) https://github.com/softprops/action-gh-release


🏁 Script executed:

# First, let's find and read the workflow file
find . -name "release-lsp-binary.yml" -type f

Repository: iii-hq/workers

Length of output: 100


🏁 Script executed:

# If found, read the entire workflow file to understand context
cat -n .github/workflows/release-lsp-binary.yml

Repository: iii-hq/workers

Length of output: 4363


Validate manual dispatch input against tag format before creating release.

Line 38 accepts arbitrary user input for manual dispatch without format validation. Line 46 blindly strips iii-lsp/v via parameter expansion, producing invalid version metadata. More critically, the resolved tag is passed to softprops/action-gh-release@v2 (line 89) without target_commitish set. This means:

  • A malformed tag like iii-lsp/invalid creates an invalid release
  • A non-existent tag (e.g., manually-created iii-lsp/v1.0.0) is created as a new tag from the default branch, not the workflow commit
  • Release metadata is derived from unvalidated input

Push-triggered events are safe (GitHub enforces iii-lsp/v* pattern), but manual dispatch must validate tag format before processing.

Proposed fix
      - name: Resolve tag
        id: resolve
        run: |
          TAG="${{ inputs.tag || github.ref_name }}"
+         if [[ ! "$TAG" =~ ^iii-lsp/v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then
+           echo "::error::Invalid tag format: $TAG"
+           exit 1
+         fi
          echo "tag=$TAG" >> "$GITHUB_OUTPUT"
+
+      - name: Verify tag exists (manual dispatch)
+        if: github.event_name == 'workflow_dispatch'
+        env:
+          TAG: ${{ steps.resolve.outputs.tag }}
+        run: |
+          git ls-remote --exit-code --tags "https://github.com/${{ github.repository }}.git" "refs/tags/$TAG" > /dev/null
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/release-lsp-binary.yml around lines 35 - 60, The workflow
currently accepts arbitrary manual input in the Resolve tag step (TAG in
steps.resolve) and then parameter-expands away the prefix in Extract metadata
(steps.meta) without validating format, and later passes the tag to
softprops/action-gh-release@v2 without setting target_commitish; fix by
validating the resolved tag in the Resolve step (ensure it matches the expected
pattern like ^iii-lsp/v[0-9]+\.[0-9]+\.[0-9]+(?:-[a-z]+\.[0-9]+|
-dry-run\.[0-9]+)?$ or at minimum starts with "iii-lsp/v" and a semver-like
version) and fail the job early on invalid input, only allow stripping the
"iii-lsp/v" prefix in Extract metadata after validation (use
steps.resolve.outputs.tag), and set the release action's target_commitish to a
deterministic ref (use github.sha for manual_dispatch or github.ref for push
events) when calling softprops/action-gh-release@v2 so malformed or non-existent
tags cannot create releases from the default branch.

@guibeira guibeira merged commit f1b4874 into main Apr 9, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants