Repository navigation
Add workflow to open esphome bump PR on release #1862
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,138 @@ | ||
| name: Bump aioesphomeapi in esphome | ||
|
|
||
| on: | ||
| release: | ||
| types: [published] | ||
| workflow_dispatch: | ||
| inputs: | ||
| version: | ||
| description: "aioesphomeapi version to bump to (without v prefix)" | ||
| required: true | ||
| type: string | ||
|
|
||
| permissions: {} | ||
|
|
||
| jobs: | ||
| bump-esphome: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Determine version | ||
| id: version | ||
| env: | ||
| TAG_NAME: ${{ github.event.release.tag_name }} | ||
| INPUT_VERSION: ${{ inputs.version }} | ||
| run: | | ||
| if [[ -n "$INPUT_VERSION" ]]; then | ||
| version="$INPUT_VERSION" | ||
| else | ||
| version="${TAG_NAME#v}" | ||
| fi | ||
| echo "version=$version" >> "$GITHUB_OUTPUT" | ||
|
|
||
| - name: Wait for PyPI to index the release | ||
| env: | ||
| VERSION: ${{ steps.version.outputs.version }} | ||
| run: | | ||
| for _ in $(seq 1 90); do | ||
| if curl -sfo /dev/null "https://pypi.org/pypi/aioesphomeapi/$VERSION/json"; then | ||
| exit 0 | ||
| fi | ||
| sleep 30 | ||
| done | ||
| echo "aioesphomeapi $VERSION never appeared on PyPI" >&2 | ||
| exit 1 | ||
|
coderabbitai[bot] marked this conversation as resolved.
Resolved
|
||
|
|
||
| - name: Create GitHub App token | ||
| id: app-token | ||
| uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 | ||
| with: | ||
| client-id: ${{ vars.ESPHOME_GITHUB_APP_CLIENT_ID }} | ||
| private-key: ${{ secrets.ESPHOME_GITHUB_APP_PRIVATE_KEY }} | ||
| owner: esphome | ||
| repositories: esphome | ||
| permission-contents: write | ||
| permission-pull-requests: write | ||
|
|
||
| - name: Checkout esphome/esphome | ||
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | ||
| with: | ||
| repository: esphome/esphome | ||
| ref: dev | ||
| token: ${{ steps.app-token.outputs.token }} | ||
| path: esphome | ||
|
|
||
| - name: Update requirements.txt pin | ||
| id: bump | ||
| env: | ||
| VERSION: ${{ steps.version.outputs.version }} | ||
| working-directory: esphome | ||
| run: | | ||
| old=$(sed -n 's/^aioesphomeapi==\([0-9a-zrcb.]*\).*/\1/p' requirements.txt) | ||
| if [[ -z "$old" ]]; then | ||
| echo "aioesphomeapi pin not found in requirements.txt" >&2 | ||
| exit 1 | ||
| fi | ||
| if [[ "$old" == "$VERSION" ]]; then | ||
| echo "requirements.txt already pins aioesphomeapi==$VERSION" | ||
| echo "changed=false" >> "$GITHUB_OUTPUT" | ||
| exit 0 | ||
| fi | ||
| sed -i "s/^aioesphomeapi==.*/aioesphomeapi==$VERSION/" requirements.txt | ||
| echo "changed=true" >> "$GITHUB_OUTPUT" | ||
| echo "old=$old" >> "$GITHUB_OUTPUT" | ||
|
|
||
| - name: Build PR body from template | ||
| if: steps.bump.outputs.changed == 'true' | ||
| env: | ||
| OLD: ${{ steps.bump.outputs.old }} | ||
| VERSION: ${{ steps.version.outputs.version }} | ||
| run: | | ||
| python3 - <<'EOF' | ||
| import os | ||
| from pathlib import Path | ||
|
|
||
| old = os.environ["OLD"] | ||
| new = os.environ["VERSION"] | ||
| template = Path("esphome/.github/PULL_REQUEST_TEMPLATE.md").read_text() | ||
| description = ( | ||
| f"Bump aioesphomeapi from {old} to {new}, release notes: " | ||
| f"https://github.com/esphome/aioesphomeapi/releases/tag/v{new}" | ||
| ) | ||
| body = template.replace( | ||
| "<!-- Quick description and explanation of changes -->", description, 1 | ||
| ) | ||
| body = body.replace("- [ ] Other", "- [x] Other", 1) | ||
| Path("pr_body.md").write_text(body) | ||
|
Comment on lines
+104
to
+117
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Fill the required ESPHome PR reference. The generated body replaces only the description and After Also applies to: 132-137 🤖 Prompt for AI Agents |
||
| EOF | ||
|
|
||
| - name: Commit and push | ||
| if: steps.bump.outputs.changed == 'true' | ||
| env: | ||
| GH_TOKEN: ${{ steps.app-token.outputs.token }} | ||
| APP_SLUG: ${{ steps.app-token.outputs.app-slug }} | ||
| OLD: ${{ steps.bump.outputs.old }} | ||
| VERSION: ${{ steps.version.outputs.version }} | ||
| working-directory: esphome | ||
| run: | | ||
| bot_id=$(gh api "/users/${APP_SLUG}[bot]" --jq .id) | ||
| git config user.name "${APP_SLUG}[bot]" | ||
| git config user.email "${bot_id}+${APP_SLUG}[bot]@users.noreply.github.com" | ||
| git checkout -b bump-aioesphomeapi | ||
| git commit -am "Bump aioesphomeapi from $OLD to $VERSION" | ||
| git push --force origin bump-aioesphomeapi | ||
|
Comment on lines
+132
to
+134
|
||
|
|
||
| - name: Open draft PR | ||
| if: steps.bump.outputs.changed == 'true' | ||
| env: | ||
| GH_TOKEN: ${{ steps.app-token.outputs.token }} | ||
| OLD: ${{ steps.bump.outputs.old }} | ||
| VERSION: ${{ steps.version.outputs.version }} | ||
| run: | | ||
| title="Bump aioesphomeapi from $OLD to $VERSION" | ||
| existing=$(gh pr list --repo esphome/esphome --head bump-aioesphomeapi --state open --json number --jq '.[].number') | ||
| if [[ -n "$existing" ]]; then | ||
| gh pr edit "$existing" --repo esphome/esphome --title "$title" --body-file pr_body.md | ||
|
Comment on lines
+143
to
+146
Comment on lines
+142
to
+144
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- workflow context ---'
sed -n '1,180p' .github/workflows/bump-esphome.yml
printf '%s\n' '--- gh usage in workflow ---'
rg -n -C 3 'gh pr list|gh api|gh pr edit|bump-aioesphomeapi|git push' .github/workflows/bump-esphome.ymlRepository: esphome/aioesphomeapi Length of output: 6221 🏁 Script executed: #!/bin/bash
set -eu
sed -n '1,180p' .github/workflows/bump-esphome.yml
rg -n -C 3 'gh pr list|gh api|gh pr edit|bump-aioesphomeapi|git push' .github/workflows/bump-esphome.ymlRepository: esphome/aioesphomeapi Length of output: 6167 🌐 Web query:
💡 Result: For the GitHub CLI and GitHub REST API, filtering pull requests by head branch uses different syntax and capabilities: GitHub CLI (gh pr list) The gh pr list command uses the --head flag to filter pull requests by the head branch name [1][2]. Syntax: gh pr list --head [1][3] Important Limitation: As of the latest documentation, the --head flag does not support the username:branch syntax (e.g., --head owner:branch is not supported) [1][4][5]. Users should provide only the branch name [1][3]. GitHub REST API (List pull requests) The GitHub REST API endpoint GET /repos/{owner}/{repo}/pulls allows filtering by head branch using the head query parameter [6][7]. Syntax: head=: [6][7] Requirement: For cross-repository pull requests within the same network, you must namespace the head branch with the username (e.g., octocat:test-branch) [6][8][9]. Summary Comparison Feature | GitHub CLI (gh pr list --head) | GitHub REST API (head parameter) --- | --- | --- Supported Syntax | | : Namespace Support | Not supported | Required for cross-repo PRs Primary Use | Command line filtering | Programmatic API integration Sources: [1][4][5][6][7][3] Citations:
Use an owner-qualified head filter.
🤖 Prompt for AI AgentsSource: MCP tools |
||
| else | ||
| gh pr create --repo esphome/esphome --base dev --head bump-aioesphomeapi \ | ||
| --draft --title "$title" --body-file pr_body.md | ||
| fi | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
Repository: esphome/aioesphomeapi
Length of output: 10886
🏁 Script executed:
Repository: esphome/aioesphomeapi
Length of output: 488
🌐 Web query:
site:docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions concurrency pending one running one pending cancel-in-progress💡 Result:
The terms "one running," "one pending," and "cancel-in-progress" refer to the concurrency control mechanisms used in GitHub Actions workflows [1]. When you define a
concurrencygroup, GitHub Actions ensures that only one workflow or job with that specific key is in progress at any given time [1]. The behavior of queued jobs depends on your configuration: One Running, One Pending: By default, when a workflow or job with a concurrency group is already running, any new job with the same concurrency key will enter a "pending" state [1]. It waits until the currently running job completes. By default, if another job is already "pending" in that group, it will be canceled to make room for the newest job [1]. Cancel-in-Progress: If you setcancel-in-progress: truewithin your concurrency configuration, GitHub Actions will automatically cancel any existing job or workflow that is currently running in the same concurrency group when a new job with that key is triggered [1]. This effectively stops the older task to allow the newer one to take its place immediately, rather than waiting for the previous one to finish [1]. You can define this in your workflow file as follows: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true This configuration ensures that only the latest version of the job or workflow runs for a given reference or branch [1].Citations:
🏁 Script executed:
Repository: esphome/aioesphomeapi
Length of output: 488
🏁 Script executed:
Repository: esphome/aioesphomeapi
Length of output: 325
🌐 Web query:
site:docs.github.com/actions concurrency "queue" "max" GitHub Actions💡 Result:
In GitHub Actions, the maximum number of jobs or workflow runs that can be in a pending state within a concurrency group is determined by the
queueproperty [1][2]. When using theconcurrencykeyword in your workflow, you can set thequeueproperty as follows: * single (default): At most one job or workflow run can be in a pending state at a time [1][2]. If a new job is queued, the existing pending job is canceled and replaced [1][2]. * max: Up to 100 jobs or workflow runs can be in a pending state at a time [1][2]. Once this queue limit of 100 is reached, any additional jobs or workflow runs are canceled [1][2]. Note that thequeue: maxconfiguration cannot be combined withcancel-in-progress: true, as they represent conflicting strategies for handling concurrent runs [1][2]. If you attempt to use them together, it will cause a workflow validation error [1][2].Citations:
🏁 Script executed:
Repository: esphome/aioesphomeapi
Length of output: 2695
🌐 Web query:
site:docs.github.com/actions "Concurrency group ordering is not guaranteed" OR "ordering is not guaranteed" concurrency💡 Result:
In the context of GitHub Actions, the statement that "concurrency group ordering is not guaranteed" refers to how jobs or workflow runs within the same concurrency group are processed [1][2]. While GitHub Actions processes jobs or workflow runs in the same concurrency group using a first-in-first-out (FIFO) approach based on the time each one starts waiting on the concurrency group, the actual execution order is not guaranteed [1][2]. This is because the specific start time of a job or run can vary due to infrastructure factors [1][2]. For clarity, the concurrency group feature allows you to define a string or expression to ensure that only a single job or workflow with that specific key runs at any given time [2]. If new jobs or workflow runs are triggered with the same concurrency key, the system places them into a queue (or cancels existing ones depending on the configuration) [2]. The "not guaranteed" aspect strictly pertains to the precise execution sequence of these queued items [1][2].
Citations:
Serialize shared-branch updates and bound PyPI polling.
bump-aioesphomeapiwithqueue: max. Concurrency does not guarantee release order, so add a stale-version check if every release must be processed in order.--connect-timeoutand--max-timeto the PyPIcurlrequest. The current polling loop does not bound a stalled request.esphome/esphome#<esphome PR number goes here>placeholder in generated PR bodies.🤖 Prompt for AI Agents