diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index c12cce59d..f9e47e82c 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -49,7 +49,9 @@ // Allow the container to access the host X11 display and EPICS CA "--net=host", // Make sure SELinux does not disable with access to host filesystems like tmp - "--security-opt=label=disable" + "--security-opt=label=disable", + // Allow the container to use the TUN device + "--device=/dev/net/tun" ], "mounts": [ // Mount in the user terminal config folder so it can be edited diff --git a/.github/workflows/_docs.yml b/.github/workflows/_docs.yml deleted file mode 100644 index 97533e73e..000000000 --- a/.github/workflows/_docs.yml +++ /dev/null @@ -1,55 +0,0 @@ -on: - workflow_call: - - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - name: Avoid git conflicts when tag and branch pushed at same time - if: github.ref_type == 'tag' - run: sleep 60 - - - name: Checkout - uses: actions/checkout@v7 - with: - # Need this to get version number from last tag - fetch-depth: 0 - - - name: Install system packages - run: sudo apt-get install graphviz - - - name: Install uv - uses: astral-sh/setup-uv@v10.1.0 - - - name: Build docs - run: uv run --locked tox -e docs - - - name: Remove environment.pickle - run: rm build/html/.doctrees/environment.pickle - - - name: Upload built docs artifact - uses: actions/upload-artifact@v7 - with: - name: docs - path: build - - - name: Sanitize ref name for docs version - run: echo "DOCS_VERSION=${GITHUB_REF_NAME//[^A-Za-z0-9._-]/_}" >> $GITHUB_ENV - - - name: Move to versioned directory - run: mv build/html .github/pages/$DOCS_VERSION - - - name: Write switcher.json - run: python .github/pages/make_switcher.py --add $DOCS_VERSION ${{ github.repository }} .github/pages/switcher.json - - - name: Publish Docs to gh-pages - if: github.ref_type == 'tag' || github.ref_name == 'main' - # We pin to the SHA, not the tag, for security reasons. - # https://docs.github.com/en/actions/learn-github-actions/security-hardening-for-github-actions#using-third-party-actions - uses: peaceiris/actions-gh-pages@84c30a85c19949d7eee79c4ff27748b70285e453 # v4.1.0 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: .github/pages - keep_files: true diff --git a/.github/workflows/_release.yml b/.github/workflows/_release.yml deleted file mode 100644 index 59b929293..000000000 --- a/.github/workflows/_release.yml +++ /dev/null @@ -1,32 +0,0 @@ -on: - workflow_call: - -jobs: - artifacts: - runs-on: ubuntu-latest - - steps: - - name: Download artifacts - uses: actions/download-artifact@v8 - with: - merge-multiple: true - - - name: Zip up docs - run: | - set -vxeuo pipefail - if [ -d html ]; then - mv html $GITHUB_REF_NAME - zip -r docs.zip $GITHUB_REF_NAME - rm -rf $GITHUB_REF_NAME - fi - - - name: Create GitHub Release - # We pin to the SHA, not the tag, for security reasons. - # https://docs.github.com/en/actions/learn-github-actions/security-hardening-for-github-actions#using-third-party-actions - uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3 - with: - prerelease: ${{ contains(github.ref_name, 'a') || contains(github.ref_name, 'b') || contains(github.ref_name, 'rc') }} - files: "*" - generate_release_notes: true - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2ccb56911..385bf17b5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,12 +1,10 @@ name: CI on: - push: - branches: - - main - tags: - - '*' pull_request: + push: + branches: [main] + tags: ["*"] # '*' never matches '/', so e.g. release/x tags don't build jobs: lint: @@ -19,10 +17,13 @@ jobs: with: runs-on: ubuntu-latest - docs: - uses: ./.github/workflows/_docs.yml - permissions: - contents: write + docs: # Call the docs building workflow directly + uses: DiamondLightSource/myst-version-switcher-plugin/.github/workflows/docs.yml@v0.28.0 + with: + # Whatever turns your sources into docs/_build/html at $BASE_URL. uv and Node + # are preinstalled; so: make docs · tox -e docs · npm ci && npm run docs + build-command: sudo apt-get install -y graphviz && uv run --locked tox -e docs + html-dir: build/html example: needs: test @@ -33,7 +34,7 @@ jobs: release: needs: [test, docs] - if: github.ref_type == 'tag' - uses: ./.github/workflows/_release.yml + if: github.ref_type == 'tag' # tag pushes only + uses: DiamondLightSource/myst-version-switcher-plugin/.github/workflows/release.yml@v0.28.0 permissions: - contents: write + contents: write # create the Release + attach assets diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 000000000..f56b7dafe --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,39 @@ +name: Publish + +on: + # matches ci.yml's `name:`, NOT its filename + workflow_run: + workflows: [CI] + types: [completed] + + # fork-PR previews and manual re-deploys + workflow_dispatch: + inputs: + pr: + description: "Fork PR to approve + preview (empty = re-deploy)" + required: false + default: "" + +jobs: + publish: + # Both guards fail OPEN — copy them verbatim. + # conclusion == 'success' : workflow_run fires on failures too + # head_repository == this repo : workflow_run holds a WRITE token even when a + # fork's PR triggered it (the pwn-request shape) + # The repository check keeps forks of python copier template from publishing to their own Pages. + if: >- + github.repository == 'DiamondLightSource/python-copier-template' && + (github.event_name == 'workflow_dispatch' || + (github.event.workflow_run.conclusion == 'success' && + github.event.workflow_run.head_repository.full_name == github.repository)) + uses: DiamondLightSource/myst-version-switcher-plugin/.github/workflows/publish-gh-pages.yml@v0.28.0 + with: + pr: ${{ inputs.pr }} + max-releases: "30" + max-prs: "20" + permissions: + contents: read + actions: read # gather cross-run docs artifacts + pages: write + id-token: write + statuses: write # record the fork-preview approval / preview link diff --git a/docs/conf.py b/docs/conf.py index f78540b5b..d50ff7e7d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -3,11 +3,9 @@ # This file only contains a selection of the most common options. For a full # list see the documentation: # https://www.sphinx-doc.org/en/master/usage/configuration.html - +import os import sys from importlib.metadata import version -from pathlib import Path -from subprocess import check_output import requests @@ -19,14 +17,7 @@ # The full version, including alpha/beta/rc tags. release = version(project) -# The short X.Y version. -if "+" in release: - # Not on a tag, use branch name - root = Path(__file__).absolute().parent.parent - git_branch = check_output("git branch --show-current".split(), cwd=root) - version = git_branch.decode().strip() -else: - version = release +version = os.environ.get("VERSION_NAME", "local") extensions = [ # For graphviz diagrams @@ -135,8 +126,8 @@ "json_url": switcher_json, "version_match": version, }, - "check_switcher": True, - "navbar_end": ["theme-switcher", "icon-links", "version-switcher"], + "check_switcher": False, + "navbar_end": ["theme-switcher", "navbar-icon-links", "version-switcher"], } # A dictionary of values to pass into the template engine’s context for all pages diff --git a/docs/how-to/build-docs.md b/docs/how-to/build-docs.md index 2351d0e51..ceda35213 100644 --- a/docs/how-to/build-docs.md +++ b/docs/how-to/build-docs.md @@ -41,8 +41,12 @@ $ tox -e docs-autobuild -- --watch tests (building-docs-in-ci)= ## Building docs in CI +Docs are built using the [myst-version-switcher-plugin](https://github.com/DiamondLightSource/myst-version-switcher-plugin). + After a successful run of CI Settings > Pages -![Setup GitHub Pages](../images/gh-pages-setup.png) +![Setup GitHub Pages](../images/github-pages-actions-setup.png) + +If your repo was using the ```gh-pages``` branch to publish docs, follow the [migration instructions](https://diamondlightsource.github.io/myst-version-switcher-plugin/main/how-to/) to now use Github Actions. diff --git a/docs/images/gh-pages-setup.png b/docs/images/gh-pages-setup.png deleted file mode 100644 index db083b7e7..000000000 Binary files a/docs/images/gh-pages-setup.png and /dev/null differ diff --git a/docs/images/github-pages-actions-setup.png b/docs/images/github-pages-actions-setup.png new file mode 100644 index 000000000..5727de282 Binary files /dev/null and b/docs/images/github-pages-actions-setup.png differ diff --git a/pyproject.toml b/pyproject.toml index 52dbee00e..40e3af965 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,9 @@ build-backend = "setuptools.build_meta" [project] name = "python-copier-template" +description = "Diamond's opinionated copier template for pure Python projects." dynamic = ["version"] +readme = "README.md" requires-python = ">=3.11" [dependency-groups] diff --git a/template/pyproject.toml.jinja b/template/pyproject.toml.jinja index c1bad2d8a..a6bbae0eb 100644 --- a/template/pyproject.toml.jinja +++ b/template/pyproject.toml.jinja @@ -53,8 +53,10 @@ version_file = "src/{{ package_name }}/_version.py" typeCheckingMode = "strict" {% else %} typeCheckingMode = "standard" -{% endif %}reportMissingImports = false # Ignore missing stubs in imported modules -{% endif %}{% if type_checker=="mypy" %} +{% endif %} +reportMissingImports = false # Ignore missing stubs in imported modules +{% endif %} +{% if type_checker=="mypy" %} [tool.mypy] ignore_missing_imports = true # Ignore missing stubs in imported modules {% endif %} diff --git a/template/renovate.json.jinja b/template/renovate.json.jinja index 5e52f7a6b..2d461a922 100644 --- a/template/renovate.json.jinja +++ b/template/renovate.json.jinja @@ -22,15 +22,13 @@ "actions/checkout", "astral-sh/setup-uv", "actions/upload-artifact", - "actions/download-artifact", - "softprops/action-gh-release", "codecov/codecov-action"{% if docker %}, "docker/setup-buildx-action", "docker/login-action", "docker/build-push-action", "docker/metadata-action"{% endif %}{% if pypi %}, - "pypa/gh-action-pypi-publish"{% endif %}{% if sphinx %}, - "peaceiris/actions-gh-pages"{% endif %} + "pypa/gh-action-pypi-publish", + "actions/download-artifact"{% endif %} ], "matchManagers": [ "github-actions" diff --git "a/template/{% if git_platform==\"github.com\" %}.github{% endif %}/CONTRIBUTING.md.jinja" "b/template/{% if git_platform==\"github.com\" %}.github{% endif %}/CONTRIBUTING.md.jinja" index fc2a1a036..d929faacb 100644 --- "a/template/{% if git_platform==\"github.com\" %}.github{% endif %}/CONTRIBUTING.md.jinja" +++ "b/template/{% if git_platform==\"github.com\" %}.github{% endif %}/CONTRIBUTING.md.jinja" @@ -24,4 +24,4 @@ It is recommended that developers use a [vscode devcontainer](https://code.visua This project was created using the [Diamond Light Source Copier Template](https://github.com/DiamondLightSource/python-copier-template) for Python projects. -For more information on common tasks like setting up a developer environment, running the tests, and setting a pre-commit hook, see the template's [How-to guides](https://diamondlightsource.github.io/python-copier-template/{{ _copier_answers._commit.split('-')[0] }}/how-to.html). +For more information on common tasks like setting up a developer environment, running the tests, and setting a pre-commit hook, see the template's [How-to guides](https://diamondlightsource.github.io/python-copier-template/main/how-to.html). diff --git "a/template/{% if git_platform==\"github.com\" %}.github{% endif %}/workflows/_release.yml" "b/template/{% if git_platform==\"github.com\" %}.github{% endif %}/workflows/_release.yml" deleted file mode 120000 index d5d5c173f..000000000 --- "a/template/{% if git_platform==\"github.com\" %}.github{% endif %}/workflows/_release.yml" +++ /dev/null @@ -1 +0,0 @@ -../../../.github/workflows/_release.yml \ No newline at end of file diff --git "a/template/{% if git_platform==\"github.com\" %}.github{% endif %}/workflows/ci.yml.jinja" "b/template/{% if git_platform==\"github.com\" %}.github{% endif %}/workflows/ci.yml.jinja" index 49133a9e1..bef07caf7 100644 --- "a/template/{% if git_platform==\"github.com\" %}.github{% endif %}/workflows/ci.yml.jinja" +++ "b/template/{% if git_platform==\"github.com\" %}.github{% endif %}/workflows/ci.yml.jinja" @@ -38,10 +38,13 @@ jobs: packages: write {% endraw %}{% endif %}{% if sphinx %} docs: - uses: ./.github/workflows/_docs.yml - permissions: - contents: write -{% endif %} + uses: DiamondLightSource/myst-version-switcher-plugin/.github/workflows/docs.yml@v0.28.0 + with: + # Whatever turns your sources into docs/_build/html at $BASE_URL. + # uv and Node are preinstalled; so: make docs · tox -e docs · npm ci && npm run docs + build-command: sudo apt-get install -y graphviz && uv run --locked tox -e docs + html-dir: build/html + {% endif %} dist: uses: ./.github/workflows/_dist.yml {% if pypi %} @@ -55,6 +58,6 @@ jobs: release: needs: [dist, test{% if sphinx %}, docs{% endif %}] if: github.ref_type == 'tag' - uses: ./.github/workflows/_release.yml + uses: DiamondLightSource/myst-version-switcher-plugin/.github/workflows/release.yml@v0.28.0 permissions: contents: write diff --git "a/template/{% if git_platform==\"github.com\" %}.github{% endif %}/workflows/publish.yml" "b/template/{% if git_platform==\"github.com\" %}.github{% endif %}/workflows/publish.yml" new file mode 100644 index 000000000..653138996 --- /dev/null +++ "b/template/{% if git_platform==\"github.com\" %}.github{% endif %}/workflows/publish.yml" @@ -0,0 +1,39 @@ +name: Publish + +on: + # matches ci.yml's `name:`, NOT its filename + workflow_run: + workflows: [CI] + types: [completed] + + # fork-PR previews and manual re-deploys + workflow_dispatch: + inputs: + pr: + description: "Fork PR to approve + preview (empty = re-deploy)" + required: false + default: "" + +jobs: + publish: + # Both guards fail OPEN — copy them verbatim. + # conclusion == 'success' : workflow_run fires on failures too + # head_repository == this repo : workflow_run holds a WRITE token even when a + # fork's PR triggered it (the pwn-request shape) + # The repository check keeps forks of blueapi from publishing to their own Pages. + if: >- + github.repository == {{ package_name}}/{{repo_name }} && + (github.event_name == 'workflow_dispatch' || + (github.event.workflow_run.conclusion == 'success' && + github.event.workflow_run.head_repository.full_name == github.repository)) + uses: DiamondLightSource/myst-version-switcher-plugin/.github/workflows/publish-gh-pages.yml@v0.28.0 + with: + pr: ${{ inputs.pr }} + max-releases: "30" + max-prs: "20" + permissions: + contents: read + actions: read # gather cross-run docs artifacts + pages: write + id-token: write + statuses: write # record the fork-preview approval / preview link diff --git "a/template/{% if git_platform==\"github.com\" %}.github{% endif %}/workflows/{% if sphinx %}_docs.yml{% endif %}" "b/template/{% if git_platform==\"github.com\" %}.github{% endif %}/workflows/{% if sphinx %}_docs.yml{% endif %}" deleted file mode 120000 index 6f47d301b..000000000 --- "a/template/{% if git_platform==\"github.com\" %}.github{% endif %}/workflows/{% if sphinx %}_docs.yml{% endif %}" +++ /dev/null @@ -1 +0,0 @@ -../../../.github/workflows/_docs.yml \ No newline at end of file diff --git a/template/{% if sphinx %}docs{% endif %}/conf.py.jinja b/template/{% if sphinx %}docs{% endif %}/conf.py.jinja index 92ea6b5f1..03eb63735 100644 --- a/template/{% if sphinx %}docs{% endif %}/conf.py.jinja +++ b/template/{% if sphinx %}docs{% endif %}/conf.py.jinja @@ -168,7 +168,7 @@ html_theme_options = { "version_match": version, }, "check_switcher": False, - "navbar_end": ["theme-switcher", "icon-links", "version-switcher"], + "navbar_end": ["theme-switcher", "navbar-icon-links", "version-switcher"], "navigation_with_keys": False, }