Skip to content

ci: auto-create GitHub release when release PR is merged#3023

Merged
xingyaoww merged 7 commits into
mainfrom
ci/auto-create-release-on-merge
May 4, 2026
Merged

ci: auto-create GitHub release when release PR is merged#3023
xingyaoww merged 7 commits into
mainfrom
ci/auto-create-release-on-merge

Conversation

@xingyaoww

@xingyaoww xingyaoww commented Apr 30, 2026

Copy link
Copy Markdown
Member

Summary

Automates the manual "create GitHub release" step that currently sits between merging the release PR and PyPI publication.

New workflow: create-release.yml

Triggers when a rel-* branch PR is merged into main. It:

  1. Extracts the version from the branch name (e.g., rel-1.19.11.19.1)
  2. Validates the version format
  3. Skips if a release already exists (idempotent)
  4. Creates a GitHub release with tag v<version>, targeting main, with auto-generated release notes

This chains into the existing pipeline:

merge release PR → create-release.yml → pypi-release.yml → version-bump-prs.yml + Slack

Other changes

  • prepare-release.yml: Updated the PR body template to explain the automated post-merge flow instead of listing manual release creation steps
  • sdk-release skill: Updated to document the automated pipeline; checklist now marks post-merge steps as (Automated)

Safety consideration

The safety guardrail shifts entirely to the merge decision — once the PR is merged, the full release pipeline fires automatically. The skill doc reflects this by emphasizing human approval at the merge step.


This PR was created by an AI agent (OpenHands) on behalf of the user.

@xingyaoww can click here to continue refining the PR


Agent Server images for this PR

GHCR package: https://github.com/OpenHands/agent-sdk/pkgs/container/agent-server

Variants & Base Images

Variant Architectures Base Image Docs / Tags
java amd64, arm64 eclipse-temurin:17-jdk Link
python amd64, arm64 nikolaik/python-nodejs:python3.13-nodejs22-slim Link
golang amd64, arm64 golang:1.21-bookworm Link

Pull (multi-arch manifest)

# Each variant is a multi-arch manifest supporting both amd64 and arm64
docker pull ghcr.io/openhands/agent-server:04e850d-python

Run

docker run -it --rm \
  -p 8000:8000 \
  --name agent-server-04e850d-python \
  ghcr.io/openhands/agent-server:04e850d-python

All tags pushed for this build

ghcr.io/openhands/agent-server:04e850d-golang-amd64
ghcr.io/openhands/agent-server:04e850d-golang_tag_1.21-bookworm-amd64
ghcr.io/openhands/agent-server:04e850d-golang-arm64
ghcr.io/openhands/agent-server:04e850d-golang_tag_1.21-bookworm-arm64
ghcr.io/openhands/agent-server:04e850d-java-amd64
ghcr.io/openhands/agent-server:04e850d-eclipse-temurin_tag_17-jdk-amd64
ghcr.io/openhands/agent-server:04e850d-java-arm64
ghcr.io/openhands/agent-server:04e850d-eclipse-temurin_tag_17-jdk-arm64
ghcr.io/openhands/agent-server:04e850d-python-amd64
ghcr.io/openhands/agent-server:04e850d-nikolaik_s_python-nodejs_tag_python3.13-nodejs22-slim-amd64
ghcr.io/openhands/agent-server:04e850d-python-arm64
ghcr.io/openhands/agent-server:04e850d-nikolaik_s_python-nodejs_tag_python3.13-nodejs22-slim-arm64
ghcr.io/openhands/agent-server:04e850d-golang
ghcr.io/openhands/agent-server:04e850d-java
ghcr.io/openhands/agent-server:04e850d-python

About Multi-Architecture Support

  • Each variant tag (e.g., 04e850d-python) is a multi-arch manifest supporting both amd64 and arm64
  • Docker automatically pulls the correct architecture for your platform
  • Individual architecture tags (e.g., 04e850d-python-amd64) are also available if needed

Add create-release.yml workflow that triggers when a rel-* branch PR is
merged into main. It extracts the version from the branch name, creates
a GitHub release with auto-generated notes, which then chains into the
existing pypi-release and version-bump-prs workflows.

Also update prepare-release.yml PR template and the sdk-release skill
to reflect the fully automated post-merge pipeline.

Co-authored-by: openhands <openhands@all-hands.dev>
@github-actions

github-actions Bot commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

REST API breakage checks (OpenAPI) — ✅ PASSED

Result:PASSED

Action log

@github-actions

github-actions Bot commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

Python API breakage checks — ✅ PASSED

Result:PASSED

Action log

Using github.event.pull_request.merge_commit_sha ensures the tag points
at exactly the release PR merge commit, even if other PRs land on main
before the workflow runs.

Co-authored-by: openhands <openhands@all-hands.dev>
Use --notes-start-tag with the latest existing release tag so
auto-generated notes compare exactly from the previous release,
matching the behavior of manually selecting 'Previous tag' in the
GitHub UI.

Co-authored-by: openhands <openhands@all-hands.dev>

Copy link
Copy Markdown
Member Author

✅ End-to-end test passed in xingyaoww/release-exp

Tested the full flow: prepare-release → merge release PR → create-release auto-triggers → GitHub release created.

Workflow run

Verified

Check Result
Workflow triggered on PR merge ✅ Triggered by merging PR #1 (rel-0.1.0main)
Version extracted from branch rel-0.1.00.1.0
Previous tag detected v0.0.0 (via gh release list)
Tag target = merge commit SHA f37920d matches PR merge commit
Lightweight tag (matching convention) object.type == "commit"
Release notes compare from previous tag Full Changelog: v0.0.0...v0.1.0
Auto-generated release notes content ✅ Includes "What's Changed" and "New Contributors" sections

Workflow log highlights

📦 Version: 0.1.0
📌 Previous release tag: v0.0.0
✅ Release v0.1.0 created!
🔗 https://github.com/xingyaoww/release-exp/releases/tag/v0.1.0

This comment was created by an AI agent (OpenHands) on behalf of the user.

@xingyaoww xingyaoww marked this pull request as ready for review April 30, 2026 17:26

@all-hands-bot all-hands-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Clean automation that removes a manual release step. The workflow is well-designed with proper validation, idempotency, and error handling. One minor documentation note inline about Slack notifications.

Comment thread .agents/skills/sdk-release/SKILL.md Outdated

@all-hands-bot all-hands-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

✅ QA Report: PASS

This PR successfully automates GitHub release creation. The workflow correctly triggers on merged release PRs, validates inputs, creates releases with auto-generated notes, and chains into the existing PyPI publication pipeline.

Does this PR achieve its stated goal?

Yes. The PR eliminates the manual "create GitHub release" step that previously took ~25 minutes between merging the release PR and PyPI publication. The new create-release.yml workflow automatically detects merged rel-* PRs, extracts the version, validates the format, checks for duplicate releases (idempotent), and creates the release with the correct target commit and auto-generated notes. The workflow integrates correctly with pypi-release.yml (which triggers on release.published) and the documentation accurately reflects the new automated flow.

Phase Result
Environment Setup ✅ gh CLI v2.89.0 available, YAML syntax valid
CI Status ✅ All core checks passing (1 unrelated docker build failure)
Functional Verification ✅ All workflow logic verified
Functional Verification

Test 1: Version Extraction and Validation

Baseline — Understanding the requirement:
The workflow must extract version numbers from branch names like rel-1.19.1 and validate they match the semver format X.Y.Z. Invalid formats should fail early.

Verification:
Ran version extraction script testing 5 scenarios:

/tmp/test_version_extraction.sh

Output:

=== Testing Version Extraction Logic ===
✅ Test 1 PASSED: Extracted version '1.19.1' from branch 'rel-1.19.1'
✅ Test 2 PASSED: Extracted version '2.0.0' from branch 'rel-2.0.0'
✅ Test 3 PASSED: Correctly rejected invalid version '1.19' from branch 'rel-1.19'
✅ Test 4 PASSED: Correctly rejected invalid version 'alpha' from branch 'rel-alpha'
✅ Test 5 PASSED: Correctly rejected non-release branch 'feature-foo'
=== All version extraction tests passed! ===

This confirms the regex ^[0-9]+\.[0-9]+\.[0-9]+$ correctly validates semver versions and rejects malformed input.


Test 2: GitHub CLI Commands

Baseline — Command syntax must be valid:
The workflow uses gh release list, gh release view, and gh release create with specific flags. These commands must exist and accept the provided arguments.

Verification:
Tested each command pattern used in the workflow:

# Test 1: List releases to find previous tag
gh release list --repo OpenHands/software-agent-sdk \
  --exclude-drafts --exclude-pre-releases --limit 1 \
  --json tagName --jq '.[0].tagName'

Output: v1.19.1

# Test 2: Check if a release exists (existing release)
gh release view "v1.19.1" --repo OpenHands/software-agent-sdk > /dev/null 2>&1 && echo "exists"

Output: exists

# Test 3: Check if a release exists (non-existent release)
gh release view "v99.99.99" --repo OpenHands/software-agent-sdk > /dev/null 2>&1 || echo "does not exist"

Output: does not exist

# Test 4: Verify gh release create flags
gh release create --help | grep -E "(--target|--title|--generate-notes|--notes-start-tag)"

Confirmed all flags exist and match the workflow's usage ✅

All commands execute successfully with correct syntax.


Test 3: NOTES_FLAG Array Logic

Baseline — Optional flag handling:
The workflow conditionally adds --notes-start-tag <PREV_TAG> only when a previous release exists. For the first release, the flag should be omitted.

Verification:
Tested bash array expansion logic:

# Test with PREV_TAG set
PREV_TAG="v1.19.0"
NOTES_FLAG=()
if [ -n "$PREV_TAG" ]; then
  NOTES_FLAG=(--notes-start-tag "$PREV_TAG")
fi
echo "${NOTES_FLAG[*]}"

Output: --notes-start-tag v1.19.0

# Test with PREV_TAG empty
PREV_TAG=""
NOTES_FLAG=()
if [ -n "$PREV_TAG" ]; then
  NOTES_FLAG=(--notes-start-tag "$PREV_TAG")
fi
echo "${NOTES_FLAG[*]}"

Output: `` (empty, as expected) ✅

The array expansion "${NOTES_FLAG[@]}" correctly handles both cases without syntax errors.


Test 4: Idempotency

Baseline — Prevent duplicate releases:
If a release already exists (e.g., from a manual creation or workflow re-run), the workflow should skip release creation gracefully.

Verification:

VERSION="1.19.1"
if gh release view "v${VERSION}" --repo OpenHands/software-agent-sdk > /dev/null 2>&1; then
  echo "Release exists, would skip"
fi

Output: Release exists, would skip

The workflow's steps.check.outputs.exists condition correctly prevents duplicate releases.


Test 5: Integration with pypi-release Workflow

Baseline — Workflow chaining:
The new workflow must trigger the existing pypi-release.yml workflow, which is configured to run on release.types: [published].

Verification:
Checked pypi-release.yml trigger:

grep -A5 "^on:" .github/workflows/pypi-release.yml

Output:

on:
  workflow_dispatch:
  release:
    types: [published]

Confirmed the chain: create-release.yml creates a release → GitHub emits release.published event → pypi-release.yml runs automatically ✅


Test 6: Complete Workflow Simulation

Baseline — End-to-end execution:
Simulated what happens when a rel-1.20.0 PR is merged.

Verification:

/tmp/test_complete_workflow.sh

Output:

=== Simulating Complete Workflow Execution ===

Step 1: Extract version from branch name
  ✅ Extracted version: 1.20.0

Step 2: Check if release already exists
  ✅ Release v1.20.0 does not exist, proceeding

Step 3: Find previous release tag
  ✅ Previous tag: v1.19.1

Step 4: Prepare release creation command
  Would execute:
    gh release create v1.20.0 \
      --repo OpenHands/software-agent-sdk \
      --target <MERGE_COMMIT_SHA> \
      --title v1.20.0 \
      --generate-notes \
      --notes-start-tag v1.19.1

  ✅ Command syntax is valid

=== Workflow simulation completed successfully! ===

All steps execute in the correct order with valid logic ✅


Test 7: Before/After Comparison

Before this PR:
Checked recent release PR #3019 (rel-1.19.1):

  • PR merged: 2026-04-30T16:41:16Z
  • Release created: 2026-04-30T17:06:25Z (by xingyaoww)
  • Manual delay: 25.1 minutes

After this PR:
The workflow triggers immediately on merge, eliminating the manual step and 25-minute delay.

Documentation changes verified:

  • prepare-release.yml PR template: Manual checklist items replaced with "What happens on merge" section explaining automation ✅
  • sdk-release skill: Phase 6 changed from "Create and Publish the GitHub Release" (manual) to "Automated Release Pipeline (no action needed)" ✅
  • Checklist updated: Manual "create GitHub release" step marked as _(Automated)_

Issues Found

None.

@xingyaoww xingyaoww requested a review from neubig April 30, 2026 18:30
openhands-agent and others added 2 commits May 3, 2026 16:08
Move Slack notification out of the automated Phase 6 pipeline and into
a new Phase 7 (Post-Release Announcements) as a human-performed step.
Update the Quick Reference checklist accordingly.

Co-authored-by: openhands <openhands@all-hands.dev>
Comment thread .agents/skills/sdk-release/SKILL.md Outdated
Keep the copy-pasteable Slack message template so the human can easily
compose the post-release announcement.

Co-authored-by: openhands <openhands@all-hands.dev>
@xingyaoww xingyaoww enabled auto-merge (squash) May 4, 2026 14:04
@xingyaoww xingyaoww disabled auto-merge May 4, 2026 14:04
@xingyaoww xingyaoww requested a review from all-hands-bot May 4, 2026 14:04
@xingyaoww xingyaoww enabled auto-merge (squash) May 4, 2026 14:04
@xingyaoww xingyaoww merged commit a6201c3 into main May 4, 2026
31 of 33 checks passed
@xingyaoww xingyaoww deleted the ci/auto-create-release-on-merge branch May 4, 2026 14:05

@all-hands-bot all-hands-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🟡 Acceptable - Solid automation design with one misleading output issue and a minor validation observation.

[IMPROVEMENT OPPORTUNITIES]

  • Summary step should be conditional to avoid misleading output

[RISK ASSESSMENT]

  • [Overall PR] ⚠️ Risk Assessment: 🟡 MEDIUM

This PR shifts the release safety checkpoint from "create GitHub release" to "merge release PR". Once merged, the full pipeline (GitHub release → PyPI publish → version bump PRs) executes automatically. The risk is mitigated by:

  • Explicit warnings in the skill doc emphasizing that merging is effectively irreversible
  • Idempotent release creation (won't duplicate if run multiple times)
  • Standard GitHub APIs and safe workflow patterns

The MEDIUM rating reflects that this changes a production release workflow and removes a manual checkpoint, but the design is sound and includes appropriate safeguards.

VERDICT:
Worth merging after addressing the Summary step issue

KEY INSIGHT:
Automating release creation is a solid workflow improvement, but the Summary step needs to be conditional to accurately reflect whether a release was created or skipped due to idempotency.

echo "" >> "$GITHUB_STEP_SUMMARY"
echo "- **Tag**: v${VERSION}" >> "$GITHUB_STEP_SUMMARY"
echo "- **Release**: https://github.com/${{ github.repository }}/releases/tag/v${VERSION}" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🟠 Important: The Summary step runs unconditionally, even when the release already exists and was skipped. This produces misleading output saying "Release v{VERSION} Created" when it was actually skipped.

Fix: Add a condition to this step:

- name: Summary
  if: steps.check.outputs.exists == 'false'
  env:
      VERSION: ${{ steps.version.outputs.version }}
  run: |

Or add a conditional message that says "Release v{VERSION} already exists, skipped" when steps.check.outputs.exists == 'true'.

BRANCH="${{ github.event.pull_request.head.ref }}"
VERSION="${BRANCH#rel-}"

if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🟡 Suggestion: The version regex ^[0-9]+\.[0-9]+\.[0-9]+$ only accepts semantic versions with exactly 3 parts (e.g., 1.19.1).

If the project ever uses pre-release versions like 1.0.0-rc1 or 1.0.0-alpha.1, this will fail.

Given the current versioning scheme uses simple semantic versions, this is probably fine. Just noting it for future reference in case versioning conventions change.

@all-hands-bot all-hands-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

✅ QA Report: PASS WITH LIMITATION

All workflow components verified successfully through functional testing; full end-to-end verification requires a real release PR merge.

Does this PR achieve its stated goal?

Yes, with high confidence based on component testing. The PR successfully automates GitHub release creation when a release PR is merged. I verified all individual workflow components function correctly: version extraction, validation, release existence checks, previous release tag detection, and GitHub CLI command syntax. The workflow is now live in the repository and correctly triggered (then skipped) when this PR was merged to main, confirming the trigger mechanism works. While I could not execute the full release creation flow (which would require merging an actual rel-* branch and creating a real release), all testable components demonstrate the workflow will function as designed.

Phase Result
Environment Setup ✅ Repository checked out, gh CLI available
CI Status ✅ 21 checks passing, 1 unrelated review thread check failing, 7 builds pending
Functional Verification ✅ All workflow components verified, integration confirmed
Functional Verification

Test 1: Version Extraction and Validation

Step 1 — Test the workflow's version extraction logic:

Ran a test script simulating the workflow's bash logic for extracting versions from release branch names:

#!/bin/bash
BRANCH="rel-1.19.1"
VERSION="${BRANCH#rel-}"
if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
  echo "Invalid version"
  exit 1
fi
echo "Version: $VERSION"

Output:

PASS: Branch 'rel-1.19.1' → Version '1.19.1'
PASS: Branch 'rel-0.0.1' → Version '0.0.1'
PASS: Branch 'rel-10.20.30' → Version '10.20.30'
PASS: Correctly rejected 'rel-1.19' (missing patch version)
PASS: Correctly rejected 'rel-v1.19.1' (has 'v' prefix)
PASS: Correctly rejected 'feature-branch' (not a release branch)
✅ All version extraction tests passed!

Interpretation: The version extraction logic correctly handles valid semver formats and rejects invalid patterns, confirming the workflow will properly validate release branch names.


Test 2: Release Existence Check (Idempotency)

Step 1 — Verify the workflow can detect existing releases:

Ran gh release view commands to test the idempotency logic:

VERSION="1.19.1"
gh release view "v${VERSION}" --repo "OpenHands/software-agent-sdk" > /dev/null 2>&1
echo "exists=true"

Output:

✅ PASS: Successfully detected that release v1.19.1 exists
✅ PASS: Correctly identified that release v999.999.999 does not exist
✅ All idempotency tests passed!

Interpretation: The workflow's idempotency check correctly identifies existing releases and would skip duplicate creation, preventing errors from re-running the workflow.


Test 3: Previous Release Tag Detection

Ran the workflow's command to find the latest release:

PREV_TAG=$(gh release list --repo "OpenHands/software-agent-sdk" \
  --exclude-drafts --exclude-pre-releases --limit 1 \
  --json tagName --jq '.[0].tagName')
echo "Previous release tag: ${PREV_TAG}"

Output:

📌 Previous release tag: v1.19.1
✅ PASS: Found previous release tag: v1.19.1

Interpretation: The workflow successfully retrieves the previous release tag, which will be used for generating accurate release notes that cover changes since the last release.


Test 4: GitHub CLI Command Syntax Validation

Verified all flags used in the workflow are valid:

gh release create --help | grep -E "(--target|--title|--generate-notes|--notes-start-tag)"

Output:

--generate-notes               Automatically generate title and notes for the release
--notes-start-tag string       Tag to use as the starting point for generating release notes
--target branch                Target branch or full commit SHA
-t, --title string             Release title

Interpretation: All flags used in the gh release create command are valid and supported by the GitHub CLI.


Test 5: Workflow Trigger Conditions

Simulated the workflow's trigger conditions:

if [ "$pr_merged" = "true" ] && [[ "$head_ref" == rel-* ]]; then
  echo "TRIGGER"
else
  echo "SKIP"
fi

Output:

✅ PASS: merged=true, head.ref=rel-1.19.1 → TRIGGER
✅ PASS: merged=false, head.ref=rel-1.19.1 → SKIP
✅ PASS: merged=true, head.ref=feature/add-something → SKIP
✅ All workflow trigger condition tests passed!

Interpretation: The workflow trigger logic correctly identifies when to run (merged release PRs) and when to skip (closed-but-not-merged PRs, non-release branches).


Test 6: Workflow YAML Syntax

Validated workflow syntax:

yamllint -d relaxed .github/workflows/create-release.yml

Output:

✅ PASS: YAML syntax is valid

Interpretation: The workflow file is syntactically correct and will be parsed properly by GitHub Actions.


Test 7: Integration with Existing Pipeline

Verified pypi-release.yml trigger configuration:

grep -A 10 "^on:" .github/workflows/pypi-release.yml

Output:

on:
  workflow_dispatch:
  release:
    types: [published]

Interpretation: The pypi-release.yml workflow is configured to trigger on release: types: [published], confirming it will automatically run when create-release.yml publishes a new release. The pipeline chain is correctly established:

merge rel-* PR → create-release.yml → pypi-release.yml → version-bump-prs.yml

Test 8: Workflow Permissions

Verified required permissions:

grep -A 2 "permissions:" .github/workflows/create-release.yml

Output:

permissions:
  contents: write

Interpretation: The workflow has the required contents: write permission to create releases.


Test 9: Live Workflow Trigger Verification

After this PR was merged to main, checked if the workflow triggered:

gh run list --repo OpenHands/software-agent-sdk \
  --workflow "Create GitHub Release" --limit 5

Output:

{
  "conclusion": "skipped",
  "createdAt": "2026-05-04T14:05:22Z",
  "event": "pull_request",
  "headBranch": "ci/auto-create-release-on-merge"
}

Interpretation: The workflow was successfully triggered when this PR was merged (4 seconds after merge at 14:05:18Z), and correctly skipped execution because the head branch ci/auto-create-release-on-merge does not start with rel-. This confirms the trigger mechanism and branch filtering work correctly in production.


Test 10: Documentation Consistency

Verified all documentation updates align with the automation:

  1. prepare-release.yml PR template — Removed manual release creation checklist items, added "What happens on merge" section describing automation
  2. sdk-release skill — Updated Phase 6 from "Create and Publish the GitHub Release" to "Automated Release Pipeline (no action needed)", removed human approval checkpoints for release creation
  3. Workflow description comments — Clearly document the workflow's purpose and integration point

Interpretation: All documentation consistently reflects the automated workflow and correctly removes manual release creation instructions.

Unable to Verify

Full End-to-End Release Creation

What could not be verified: Actually creating a GitHub release by merging a real rel-* branch PR.

What was attempted: I verified all individual components (version extraction, validation, release checks, CLI syntax, trigger conditions, permissions, integration points) and confirmed the workflow is live and correctly triggered when this PR was merged. However, actually executing the release creation step would require:

  1. Creating a rel-X.Y.Z branch with real version bumps
  2. Opening a release PR
  3. Merging that PR to main
  4. Observing the workflow create a GitHub release

This would create a real release in the repository, which I should not do without explicit permission.

Confidence level: Very high. All testable components work correctly, the workflow is syntactically valid, the trigger mechanism is confirmed working in production, and the integration with pypi-release.yml is properly configured. The only untested step is the final gh release create execution, but since all its inputs (version, target commit, previous tag, flags) are verified correct, there is no reason to expect failure.

Suggested AGENTS.md guidance for future QA runs:

## QA Testing GitHub Actions Workflows

For workflow changes that trigger on specific events (e.g., PR merge, release publish):
1. Validate YAML syntax with `yamllint`
2. Test individual bash/shell logic in isolation
3. Verify GitHub CLI commands with `--help` to confirm flag validity
4. Check workflow trigger conditions with simulated variables
5. For workflows already merged: verify the workflow triggered correctly using `gh run list`
6. If full end-to-end testing requires destructive actions (creating releases, publishing packages), verify all components individually and document limitations

Issues Found

None.

StressTestor pushed a commit to StressTestor/software-agent-sdk that referenced this pull request Jun 1, 2026
)

Co-authored-by: openhands <openhands@all-hands.dev>
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.

3 participants