Skip to content
Merged
47 changes: 47 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Dependabot configuration for airbyte-api-python-sdk.
#
# `.speakeasy/workflow.yaml` uses `speakeasyVersion: pinned`, so the actual CLI
# version is pinned in `.github/speakeasy/dummy-compose.yml` and bumped by the
# docker-compose ecosystem entry below.

version: 2
updates:
# Speakeasy CLI version pin (image: tag in .github/speakeasy/dummy-compose.yml).
# See that file for the full explanation.
- package-ecosystem: docker-compose
directory: /.github/speakeasy
schedule:
interval: weekly
day: monday
open-pull-requests-limit: 5
commit-message:
prefix: ci(speakeasy)
labels:
- dependencies
- speakeasy

# GitHub Actions used in .github/workflows/*.yml
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
day: monday
open-pull-requests-limit: 5
commit-message:
prefix: ci
labels:
- dependencies
- github-actions

# Python dependencies (uv / pyproject.toml)
- package-ecosystem: pip
directory: /
schedule:
interval: weekly
day: monday
open-pull-requests-limit: 5
commit-message:
prefix: chore
labels:
- dependencies
- python
32 changes: 8 additions & 24 deletions .github/workflows/generate-command.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,29 +66,18 @@ jobs:
pull-requests: write
steps:
- name: Authenticate as GitHub App
if: ${{ !inputs.dry_run && github.event.inputs.pr != '' }}
uses: actions/create-github-app-token@v3
id: get-app-token
continue-on-error: true
id: app-token
with:
app-id: ${{ secrets.OCTAVIA_BOT_APP_ID }}
private-key: ${{ secrets.OCTAVIA_BOT_PRIVATE_KEY }}
Comment on lines 68 to 73

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔴 Removing app-token fallback to github.token breaks dry_run workflow_call path

The old code conditionally created the GitHub App token (only when !inputs.dry_run && github.event.inputs.pr != ''), had continue-on-error: true, and fell back to github.token via a dedicated "Set working token" step. The new code always runs the create-github-app-token step unconditionally (no if, no continue-on-error) and removes the fallback entirely.

When test-full.yml calls this workflow via workflow_call with dry_run: true (.github/workflows/test-full.yml:53-56), the app token step now runs even though it's unnecessary for dry-run mode. For fork PRs, secrets.OCTAVIA_BOT_APP_ID and secrets.OCTAVIA_BOT_PRIVATE_KEY are unavailable (GitHub does not pass repository secrets to fork PR workflows), causing the step to fail hard and blocking the entire CI validation pipeline. The old code gracefully handled this by skipping the step in dry-run mode and falling back to github.token for checkout.

Old code had explicit fallback logic

The old code at the base revision had:

- name: Authenticate as GitHub App
  if: ${{ !inputs.dry_run && github.event.inputs.pr != '' }}
  continue-on-error: true
  ...
- name: Set working token
  run: |
    if [ -n "${{ steps.get-app-token.outputs.token }}" ]; then
        echo "token=${{ steps.get-app-token.outputs.token }}" | tee -a $GITHUB_OUTPUT
    else
        echo "token=${{ github.token }}" | tee -a $GITHUB_OUTPUT
    fi

Checkout also had a double fallback: token: ${{ steps.token.outputs.token || github.token }}

Prompt for agents
The Authenticate as GitHub App step in generate-command.yml (lines 68-73) was changed to run unconditionally without continue-on-error and without a fallback to github.token. This breaks the workflow_call path from test-full.yml when secrets are unavailable (fork PRs).

The fix should either:
1. Restore the conditional: add `if: ${{ !inputs.dry_run }}` and `continue-on-error: true` to the app token step, and add a fallback that uses `github.token` when the app token is not available.
2. Or at minimum, add `continue-on-error: true` and use an expression like `steps.app-token.outputs.token || github.token` in the checkout step's token field.

Affected files:
- .github/workflows/generate-command.yml: lines 68-73 (app token step), line 111 (checkout token)

The checkout step at line 111 currently uses `token: ${{ steps.app-token.outputs.token }}` with no fallback. The old code used `token: ${{ steps.token.outputs.token || github.token }}`.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.


- name: Set working token
id: token
run: |
if [ -n "${{ steps.get-app-token.outputs.token }}" ]; then
echo "token=${{ steps.get-app-token.outputs.token }}" | tee -a $GITHUB_OUTPUT
else
echo "token=${{ github.token }}" | tee -a $GITHUB_OUTPUT
fi

- name: Post or append starting comment
if: ${{ !inputs.dry_run && github.event.inputs.pr != '' }}
id: start-comment
uses: peter-evans/create-or-update-comment@v5
with:
token: ${{ steps.token.outputs.token }}
token: ${{ steps.app-token.outputs.token }}
issue-number: ${{ github.event.inputs.pr }}
comment-id: ${{ github.event.inputs.comment-id || '' }}
body: |
Expand All @@ -102,7 +91,7 @@ jobs:
if: ${{ !inputs.dry_run && github.event.inputs.pr != '' }}
id: pr-branch
env:
GH_TOKEN: ${{ steps.token.outputs.token }}
GH_TOKEN: ${{ steps.app-token.outputs.token }}
PR_NUMBER: ${{ github.event.inputs.pr }}
run: |
PR_JSON=$(gh api repos/${{ github.repository }}/pulls/${PR_NUMBER})
Expand All @@ -119,16 +108,11 @@ jobs:
with:
fetch-depth: 0
ref: ${{ steps.pr-branch.outputs.head_ref || '' }}
token: ${{ steps.token.outputs.token || github.token }}
token: ${{ steps.app-token.outputs.token }}

- name: Install uv
uses: astral-sh/setup-uv@v5

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Get next version from release drafter
id: get-version
uses: aaronsteers/semantic-pr-release-drafter@v1.1.0
Expand Down Expand Up @@ -241,7 +225,7 @@ jobs:
id: create-pr
uses: peter-evans/create-pull-request@v6
with:
token: ${{ steps.token.outputs.token }}
token: ${{ steps.app-token.outputs.token }}
commit-message: "chore: regenerate SDK with Speakeasy"
title: "chore: regenerate SDK with Speakeasy"
body: |
Expand All @@ -258,14 +242,14 @@ jobs:
|| github.event_name == 'schedule'
) && steps.create-pr.outputs.pull-request-operation == 'created'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: gh pr merge ${{ steps.create-pr.outputs.pull-request-number }} --auto --squash

- name: Append success comment
if: ${{ success() && !inputs.dry_run && github.event.inputs.pr != '' }}
uses: peter-evans/create-or-update-comment@v5
with:
token: ${{ steps.token.outputs.token }}
token: ${{ steps.app-token.outputs.token }}
comment-id: ${{ steps.start-comment.outputs.comment-id }}
reactions: hooray
body: |
Expand All @@ -275,7 +259,7 @@ jobs:
if: ${{ failure() && !inputs.dry_run && github.event.inputs.pr != '' }}
uses: peter-evans/create-or-update-comment@v5
with:
token: ${{ steps.token.outputs.token }}
token: ${{ steps.app-token.outputs.token }}
comment-id: ${{ steps.start-comment.outputs.comment-id }}
reactions: confused
body: |
Expand Down
137 changes: 129 additions & 8 deletions .github/workflows/pre-release-command.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,31 @@
# Stub: Pre-Release Workflow
# Pre-Release Workflow
#
# Minimal placeholder to register the workflow_dispatch trigger on main.
# Full implementation arrives in a follow-up PR.
# Builds and publishes a pre-release version of the Python SDK to PyPI.
# Pre-releases are installable via `pip install airbyte-api==1.0.0rc1` but
# are NOT the default version, so existing users are unaffected.
#
# Triggers:
# - Manual workflow_dispatch: From the Actions tab
# - Slash command: `/pre-release version=1.0.0rc1` on a PR comment
#
# Inputs:
#
# version (REQUIRED): The pre-release version string.
# Must contain a PEP 440 pre-release suffix: rcN, betaN, alphaN, devN.
# Examples: 1.0.0rc1, 1.0.0a1, 1.0.0b1, 1.0.0.dev1
#
Comment on lines +13 to +16
# ref (optional, default: main): The branch, tag, or commit SHA to build from.
# When triggered via slash command on a PR, defaults to the PR's head branch.

name: Pre-Release

on:
workflow_dispatch:
inputs:
version:
description: 'Pre-release version (e.g. 1.0.0rc1)'
description: >-
Pre-release version (e.g. 1.0.0rc1, 1.0.0a1).
Must contain a PEP 440 pre-release suffix.
required: true
type: string
ref:
Expand All @@ -26,10 +42,115 @@ on:
required: false
type: string

concurrency:
group: pre-release-${{ inputs.version }}
cancel-in-progress: true

permissions:
contents: read

jobs:
stub:
name: Stub (placeholder)
if: false
pre_release:
name: Build & Publish Pre-Release
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/project/airbyte-api/
permissions:
contents: write
pull-requests: write
id-token: write
steps:
- run: echo "stub"
# ── Slash command: post starting comment ────────────────────────
- name: Authenticate as GitHub App
uses: actions/create-github-app-token@v3
id: app-token
with:
app-id: ${{ secrets.OCTAVIA_BOT_APP_ID }}
private-key: ${{ secrets.OCTAVIA_BOT_PRIVATE_KEY }}

- name: Post starting comment
if: ${{ inputs.pr != '' }}
id: start-comment
uses: peter-evans/create-or-update-comment@v5
with:
token: ${{ steps.app-token.outputs.token }}
issue-number: ${{ inputs.pr }}
comment-id: ${{ inputs.comment-id || '' }}
body: |
> **Pre-Release Job Info**
>
> Building pre-release `${{ inputs.version }}` from ref `${{ inputs.ref || 'PR head branch' }}`.

> Job started... [Check job output.](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
Comment on lines +81 to +85

# ── Resolve ref from PR if not explicitly provided ──────────────
- name: Resolve PR head branch
if: ${{ inputs.pr != '' && inputs.ref == 'main' }}
id: resolve-ref
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: |
PR_HEAD=$(gh pr view "${{ inputs.pr }}" --repo "${{ github.repository }}" --json headRefName -q '.headRefName')
echo "ref=$PR_HEAD" >> "$GITHUB_OUTPUT"

# ── Validate version input ──────────────────────────────────────
- name: Validate pre-release version
run: |
VERSION="${{ inputs.version }}"

# PEP 440 pre-release pattern: X.Y.Z(a|b|rc|dev)N
if ! echo "$VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+(a|b|rc|dev|\.dev)[0-9]+$'; then
echo "::error::Invalid version or missing pre-release suffix. Expected PEP 440 format: X.Y.Z(a|b|rc|dev)N (e.g. 1.0.0rc1). Got: $VERSION"
exit 1
fi

echo "Pre-release version validated: $VERSION"

# ── Checkout ────────────────────────────────────────────────────
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: ${{ steps.resolve-ref.outputs.ref || inputs.ref }}

- name: Install uv
uses: astral-sh/setup-uv@v5

# ── Set version and build ───────────────────────────────────────
- name: Set pre-release version in pyproject.toml
run: |
VERSION="${{ inputs.version }}"
# Use sed to update version in pyproject.toml
sed -i "s/^version = \".*\"/version = \"${VERSION}\"/" pyproject.toml
echo "Updated pyproject.toml version to: $VERSION"
grep 'version' pyproject.toml | head -1

- name: Build package
run: uv build

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1

# ── Tag the commit ──────────────────────────────────────────────
- name: Create and push tag
run: |
VERSION="${{ inputs.version }}"
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag -a "v${VERSION}" -m "Pre-release v${VERSION}"
git push origin "v${VERSION}"
Comment on lines +135 to +141

# ── Slash command: post result comment ──────────────────────────
- name: Post result comment
if: ${{ always() && inputs.pr != '' }}
uses: peter-evans/create-or-update-comment@v5
with:
token: ${{ steps.app-token.outputs.token }}
issue-number: ${{ inputs.pr }}
body: |
> **Pre-Release Result:** ${{ job.status == 'success' && 'Published' || 'Failed' }}
>
> Version: `${{ inputs.version }}`
> Ref: `${{ steps.resolve-ref.outputs.ref || inputs.ref }}`
> [View run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
${{ job.status == 'success' && format('> Install: `pip install airbyte-api=={0}`', inputs.version) || '' }}
41 changes: 34 additions & 7 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,45 @@
# Stub: Publish to PyPI Workflow
# PyPI Publish Workflow
#
# Minimal placeholder to register the release trigger on main.
# Full implementation arrives in a follow-up PR.
# Triggered when a GitHub Release is published (draft → published).
# Builds the Python package and uploads it to PyPI using OIDC trusted publishing.
#
# Prerequisites:
# - PyPI trusted publisher configured for this repository:
# https://docs.pypi.org/trusted-publishers/creating-a-project-through-oidc/
# Owner: airbytehq
# Repository: airbyte-api-python-sdk
# Workflow: publish.yml
# Environment: pypi

name: Publish to PyPI

on:
release:
types: [published]

permissions:
contents: read

jobs:
stub:
name: Stub (placeholder)
if: false
publish:
name: Build & Publish to PyPI
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/project/airbyte-api/
permissions:
id-token: write
steps:
- run: echo "stub"
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: ${{ github.event.release.tag_name }}

- name: Install uv
uses: astral-sh/setup-uv@v5

- name: Build package
run: uv build

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
Loading
Loading