diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index dddfe6d..5fddd08 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -82,9 +82,30 @@ 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 + + - 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: @@ -92,7 +113,8 @@ jobs: 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 diff --git a/.github/workflows/dependabot-auto-merge.yaml b/.github/workflows/dependabot-auto-merge.yaml index 88564ce..89a1a13 100644 --- a/.github/workflows/dependabot-auto-merge.yaml +++ b/.github/workflows/dependabot-auto-merge.yaml @@ -1,6 +1,7 @@ name: Dependabot auto-merge -on: pull_request +on: + pull_request: permissions: contents: write @@ -8,20 +9,31 @@ permissions: 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 }} + + - 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 }} diff --git a/.github/workflows/pr-title.yaml b/.github/workflows/pr-title.yaml index 8537600..82f0046 100644 --- a/.github/workflows/pr-title.yaml +++ b/.github/workflows/pr-title.yaml @@ -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 @@ -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 }} diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml new file mode 100644 index 0000000..5582c3e --- /dev/null +++ b/.github/workflows/publish.yaml @@ -0,0 +1,71 @@ +name: Publish + +on: + push: + tags: ["v*"] + workflow_call: + inputs: + tag: + required: true + type: string + +concurrency: + group: publish-${{ inputs.tag || 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: ${{ inputs.tag || 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 }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 09038bc..14a1f18 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -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 @@ -26,7 +16,7 @@ jobs: 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 }} @@ -35,48 +25,17 @@ 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] + 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 + attestations: write + uses: ./.github/workflows/publish.yaml with: - deploy: true - version: ${{ needs.release-please.outputs.tag_name }} + tag: ${{ needs.release-please.outputs.tag_name }} diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..c8730e8 --- /dev/null +++ b/.readthedocs.yaml @@ -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