Skip to content
26 changes: 24 additions & 2 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -82,17 +82,39 @@ jobs:
files: coverage.xml
fail_ci_if_error: false

docs:
name: Docs build
runs-on: ubuntu-24.04
timeout-minutes: 5
steps:
- uses: actions/checkout@v6

- uses: astral-sh/setup-uv@v7
with:
enable-cache: true

- uses: actions/setup-python@v6
with:
python-version: "3.12"

- name: Install dependencies
run: uv sync --extra docs
Comment on lines +100 to +101
Copy link

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 uv, does uv sync --extra docsinstall packages from[dependency-groups].docs, or do dependency groups require uv sync --group docs?

💡 Result:

In uv, uv sync --extra docs does NOT install packages from [dependency-groups].docs. The --extra flag is for including optional dependencies (extras) from [project.optional-dependencies], while dependency groups from [dependency-groups] require uv sync --group docs. Dependency groups are read from the [dependency-groups] table (PEP 735). The dev group is synced by default, but other groups like docs need explicit --group docs. Options include --group, --only-group, --all-groups, --no-group, etc. --extra and --group serve distinct purposes: extras for published optional deps, groups for local dev deps.

Citations:


🏁 Script executed:

# Check if .github/workflows/ci.yaml exists and examine lines 100-101
if [ -f ".github/workflows/ci.yaml" ]; then
  echo "=== .github/workflows/ci.yaml lines 100-101 ==="
  sed -n '100,101p' ".github/workflows/ci.yaml"
else
  echo ".github/workflows/ci.yaml not found"
fi

# Check pyproject.toml for [dependency-groups] section
if [ -f "pyproject.toml" ]; then
  echo -e "\n=== pyproject.toml [dependency-groups] section ==="
  grep -A 10 "\[dependency-groups\]" pyproject.toml
else
  echo "pyproject.toml not found"
fi

# Check .readthedocs.yaml for docs sync command
if [ -f ".readthedocs.yaml" ]; then
  echo -e "\n=== .readthedocs.yaml lines 17-18 ==="
  sed -n '17,18p' ".readthedocs.yaml"
else
  echo ".readthedocs.yaml not found"
fi

Repository: FBumann/fluxopt_plot

Length of output: 559


Use --group docs here, not --extra docs.

uv sync --extra ... reads from [project.optional-dependencies], while dependency groups are selected with --group. This repo declares docs under [dependency-groups], and .readthedocs.yaml already uses the correct uv sync --group docs form, so this command is syncing the wrong dependency set.

♻️ Proposed fix
       - name: Install dependencies
-        run: uv sync --extra docs
+        run: uv sync --group docs
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/ci.yaml around lines 100 - 101, In the "Install
dependencies" step replace the incorrect uv command flag so it selects the
dependency group declared under dependency-groups: change the command string
used in the Install dependencies job from using "--extra docs" to "--group docs"
(so the job runs uv sync --group docs) to match .readthedocs.yaml and ensure the
docs dependency group is synced.


- name: Build docs
run: uv run mkdocs build --strict

ci-success:
name: CI Success
needs: [lint, typecheck, test]
needs: [lint, typecheck, test, docs]
if: always()
runs-on: ubuntu-24.04
steps:
- name: Check all jobs passed
run: |
if [[ "${{ needs.lint.result }}" != "success" || \
"${{ needs.typecheck.result }}" != "success" || \
"${{ needs.test.result }}" != "success" ]]; then
"${{ needs.test.result }}" != "success" || \
"${{ needs.docs.result }}" != "success" ]]; then
echo "::error::One or more CI jobs failed"
exit 1
fi
36 changes: 24 additions & 12 deletions .github/workflows/dependabot-auto-merge.yaml
Original file line number Diff line number Diff line change
@@ -1,27 +1,39 @@
name: Dependabot auto-merge

on: pull_request
on:
pull_request:

permissions:
contents: write
pull-requests: write

jobs:
auto-merge:
runs-on: ubuntu-24.04
name: Auto-merge patch
if: github.actor == 'dependabot[bot]'
runs-on: ubuntu-24.04
steps:
- name: Dependabot metadata
- uses: dependabot/fetch-metadata@v2
id: metadata
uses: dependabot/fetch-metadata@v2

- name: Generate app token
if: steps.metadata.outputs.update-type == 'version-update:semver-patch'
id: app-token
uses: actions/create-github-app-token@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
Comment on lines +19 to +25
Copy link

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:

When a GitHub Actions workflow is triggered by Dependabot on the pull_request event, are repository Actions secrets available, or only Dependabot secrets?

💡 Result:

When a GitHub Actions workflow is triggered by Dependabot on the pull_request event, only Dependabot secrets are available. Repository Actions secrets are not available.

Citations:


Ensure APP_ID and APP_PRIVATE_KEY are configured in Dependabot secrets.

On Dependabot-triggered pull_request runs, the secrets context is populated exclusively from Dependabot secrets; regular Actions secrets are unavailable. Since this workflow accesses ${{ secrets.APP_ID }} and ${{ secrets.APP_PRIVATE_KEY }}, these credentials must be configured in Dependabot secrets or the token generation will fail. If they only exist in the Actions secret store, the workflow cannot proceed.

Add a fast-fail check to catch missing secrets early:

Recommended fail-fast guard
+      - name: Verify Dependabot app secrets
+        if: steps.metadata.outputs.update-type == 'version-update:semver-patch'
+        env:
+          APP_ID: ${{ secrets.APP_ID }}
+          APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }}
+        run: |
+          test -n "$APP_ID" || { echo "::error::APP_ID must be configured as a Dependabot secret"; exit 1; }
+          test -n "$APP_PRIVATE_KEY" || { echo "::error::APP_PRIVATE_KEY must be configured as a Dependabot secret"; exit 1; }
+
       - name: Generate app token
         if: steps.metadata.outputs.update-type == 'version-update:semver-patch'
         id: app-token
         uses: actions/create-github-app-token@v2
📝 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
- name: Generate app token
if: steps.metadata.outputs.update-type == 'version-update:semver-patch'
id: app-token
uses: actions/create-github-app-token@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
- name: Verify Dependabot app secrets
if: steps.metadata.outputs.update-type == 'version-update:semver-patch'
env:
APP_ID: ${{ secrets.APP_ID }}
APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }}
run: |
test -n "$APP_ID" || { echo "::error::APP_ID must be configured as a Dependabot secret"; exit 1; }
test -n "$APP_PRIVATE_KEY" || { echo "::error::APP_PRIVATE_KEY must be configured as a Dependabot secret"; exit 1; }
- name: Generate app token
if: steps.metadata.outputs.update-type == 'version-update:semver-patch'
id: app-token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/dependabot-auto-merge.yaml around lines 19 - 25, Add a
fast-fail check before the "Generate app token" step (id: app-token) to verify
that secrets.APP_ID and secrets.APP_PRIVATE_KEY are present in the Dependabot
secrets context and exit early if not; create a new step (e.g., "Check
Dependabot secrets") that runs a simple shell test using the same expressions
(e.g., test -n "${{ secrets.APP_ID }}" && test -n "${{ secrets.APP_PRIVATE_KEY
}}" || { echo 'Missing APP_ID or APP_PRIVATE_KEY in Dependabot secrets'; exit 1;
}) so the workflow fails fast with a clear message instead of attempting to run
actions/create-github-app-token@v2 when those secrets are absent.


- name: Approve PR
if: steps.metadata.outputs.update-type == 'version-update:semver-patch'
run: gh pr review "$PR" --approve
env:
PR: ${{ github.event.pull_request.html_url }}
GH_TOKEN: ${{ steps.app-token.outputs.token }}

- name: Auto-merge minor and patch updates
if: >-
steps.metadata.outputs.update-type == 'version-update:semver-patch' ||
steps.metadata.outputs.update-type == 'version-update:semver-minor'
run: gh pr merge --auto --squash "$PR_URL"
- name: Enable auto-merge
if: steps.metadata.outputs.update-type == 'version-update:semver-patch'
run: gh pr merge "$PR" --auto --squash
env:
PR_URL: ${{ github.event.pull_request.html_url }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR: ${{ github.event.pull_request.html_url }}
GH_TOKEN: ${{ github.token }}
13 changes: 6 additions & 7 deletions .github/workflows/pr-title.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ on:
jobs:
validate:
name: Validate conventional commit format
if: github.event_name == 'pull_request'
runs-on: ubuntu-24.04
permissions:
pull-requests: read
steps:
- if: ${{ github.event_name != 'push' }}
uses: amannn/action-semantic-pull-request@v6
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: amannn/action-semantic-pull-request@v6
with:
types: |
feat
Expand All @@ -28,6 +28,5 @@ jobs:
requireScope: false
subjectPattern: ^.+$
subjectPatternError: "PR title must have a description after the type"

- if: ${{ github.event_name == 'push' }}
run: echo "Release Please PRs always use valid conventional commit format"
env:
GITHUB_TOKEN: ${{ github.token }}
66 changes: 66 additions & 0 deletions .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: Publish

on:
push:
tags: ["v*"]

concurrency:
group: publish-${{ github.ref_name }}
cancel-in-progress: false

permissions:
contents: write
id-token: write
attestations: write

jobs:
publish:
name: Build & publish to PyPI
runs-on: ubuntu-24.04
timeout-minutes: 10
environment:
name: pypi
url: https://pypi.org/project/fluxopt_plot
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.ref_name }}
fetch-depth: 0

- uses: astral-sh/setup-uv@v7
with:
enable-cache: true

- uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Build
run: uv build

- uses: pypa/gh-action-pypi-publish@release/v1

github-release:
name: Create GitHub Release
needs: [publish]
if: github.event_name == 'push' && needs.publish.result == 'success'
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.ref_name }}

- name: Create GitHub Release
run: |
if gh release view "$TAG" &>/dev/null; then
echo "Release $TAG already exists, skipping."
exit 0
fi
if [[ "$TAG" == *-* ]]; then
gh release create "$TAG" --generate-notes --prerelease
else
gh release create "$TAG" --generate-notes
fi
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ github.ref_name }}
59 changes: 2 additions & 57 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,6 @@ name: Release
on:
push:
branches: [main]
workflow_dispatch:
inputs:
branch:
description: Branch to create the release from
required: true
default: main
prerelease:
description: Create a pre-release
type: boolean
default: true

permissions:
contents: write
Expand All @@ -22,11 +12,8 @@ jobs:
release-please:
name: Release Please
runs-on: ubuntu-24.04
outputs:
release_created: ${{ steps.release.outputs.release_created }}
tag_name: ${{ steps.release.outputs.tag_name }}
steps:
- uses: actions/create-github-app-token@v3
- uses: actions/create-github-app-token@v2
id: app-token
with:
app-id: ${{ secrets.APP_ID }}
Expand All @@ -35,48 +22,6 @@ jobs:
- uses: googleapis/release-please-action@v4
id: release
with:
token: ${{ steps.app-token.outputs.token }}
config-file: .release-please-config.json
manifest-file: .release-please-manifest.json
token: ${{ steps.app-token.outputs.token }}
target-branch: ${{ inputs.branch || github.ref_name }}
prerelease: ${{ inputs.prerelease }}

publish:
name: Build & publish to PyPI
needs: [release-please]
if: needs.release-please.outputs.release_created
runs-on: ubuntu-24.04
timeout-minutes: 10
environment:
name: pypi
url: https://pypi.org/project/fluxopt_plot
permissions:
id-token: write
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0

- uses: astral-sh/setup-uv@v7
with:
enable-cache: true

- uses: actions/setup-python@v6
with:
python-version: "3.12"

- name: Build
run: uv build

- uses: pypa/gh-action-pypi-publish@release/v1

deploy-docs:
name: Deploy docs
needs: [release-please, publish]
if: needs.release-please.outputs.release_created
permissions:
contents: write
uses: ./.github/workflows/docs.yaml
with:
deploy: true
version: ${{ needs.release-please.outputs.tag_name }}
18 changes: 18 additions & 0 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
version: 2

mkdocs:
configuration: mkdocs.yml

build:
os: ubuntu-24.04
tools:
python: "3.13"
jobs:
pre_create_environment:
- asdf plugin add uv
- asdf install uv latest
- asdf global uv latest
create_environment:
- uv venv "${READTHEDOCS_VIRTUALENV_PATH}"
install:
- UV_PROJECT_ENVIRONMENT="${READTHEDOCS_VIRTUALENV_PATH}" uv sync --group docs
Loading