feanil/setup semantic release#16
Conversation
feanil
commented
Dec 29, 2025
- build: Invert version fetching.
- build: Add minimal config needed for python-semantic-release
- build: Add a github workflow for python-semantic-release
41cd77c to
addf512
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #16 +/- ##
==========================================
+ Coverage 88.20% 88.23% +0.02%
==========================================
Files 13 13
Lines 407 408 +1
Branches 16 16
==========================================
+ Hits 359 360 +1
Misses 40 40
Partials 8 8
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR sets up automated semantic versioning using python-semantic-release. The changes modernize version management by switching from static version strings to dynamic version fetching via importlib.metadata, and introduce a GitHub Actions workflow to automate the release process.
- Migrates from hardcoded
__version__strings to dynamic version retrieval usingimportlib.metadata.version() - Configures
pyproject.tomlfor python-semantic-release integration - Adds a new GitHub workflow for automated releases and PyPI deployments
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| backend/sample_plugin/init.py | Replaces static version string with dynamic version fetching from package metadata |
| backend/pyproject.toml | Adds static version field, removes version from dynamic list, and includes semantic_release configuration |
| backend/docs/conf.py | Migrates documentation config from custom version extraction to importlib.metadata |
| .github/workflows/release.yml | New workflow for automated semantic releases, GitHub releases, and PyPI deployment |
| .github/workflows/ci.yml | Adds workflow_call trigger to enable reuse from release workflow |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| __version__ = "0.1.0" | ||
| from importlib.metadata import version as get_version | ||
|
|
||
| # The name of the package is `opnedx-sample-plugin` but __package__ is `sample_plugin` so we hardcode the name of the |
There was a problem hiding this comment.
There's a typo in the comment. The package name is written as "opnedx-sample-plugin" but should be "openedx-sample-plugin" (missing the 'e' in 'openedx'). This inconsistency could be confusing to developers reading this code.
| # The name of the package is `opnedx-sample-plugin` but __package__ is `sample_plugin` so we hardcode the name of the | |
| # The name of the package is `openedx-sample-plugin` but __package__ is `sample_plugin` so we hardcode the name of the |
| [tool.semantic_release.changelog.default_templates] | ||
| changelog_file = "CHANGELOG.rst" | ||
| output_format = "rst" |
There was a problem hiding this comment.
The semantic release configuration appears incomplete. The 'changelog.default_templates' section shown here is not valid configuration syntax for python-semantic-release v8+. The correct configuration should use sections like [tool.semantic_release] with proper options such as version_toml, branch, changelog_file, and build_command. The current configuration with 'changelog.default_templates' and 'output_format' is not recognized by the tool and may cause the release process to fail.
| [tool.semantic_release.changelog.default_templates] | |
| changelog_file = "CHANGELOG.rst" | |
| output_format = "rst" | |
| [tool.semantic_release] | |
| version_toml = "pyproject.toml:project.version" | |
| changelog_file = "CHANGELOG.rst" |
| @@ -0,0 +1,90 @@ | |||
| name: Python CI | |||
There was a problem hiding this comment.
The workflow name is "Python CI" which is the same as the ci.yml workflow. This creates ambiguity in the GitHub Actions UI where both workflows will appear with identical names. Consider renaming this to something more specific like "Release" or "Python Release" to clearly distinguish it from the CI workflow.
| name: Python CI | |
| name: Python Release |
| user: __token__ | ||
| password: ${{ secrets.PYPI_UPLOAD_TOKEN }} |
There was a problem hiding this comment.
The pypa/gh-action-pypi-publish action is being used with deprecated parameters. The 'user' and 'password' parameters are deprecated in favor of trusted publishing. Since the job already has 'id-token: write' permission configured (line 75), which is required for trusted publishing, the 'user' and 'password' parameters should be removed to use the more secure OIDC-based trusted publisher flow instead of API tokens.
| user: __token__ | |
| password: ${{ secrets.PYPI_UPLOAD_TOKEN }} |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 7 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| description = "A sample backend plugin for the Open edX Platform" | ||
| requires-python = ">=3.11" | ||
| license="Apache-2.0" | ||
| version = "0.1.0" |
There was a problem hiding this comment.
The hardcoded version "0.1.0" conflicts with the semantic release approach. With python-semantic-release, the version should be dynamically managed by the tool. However, since you removed "version" from the dynamic list and added a static version, this creates a situation where semantic-release updates will need to modify the static version field in pyproject.toml. Ensure that your semantic_release configuration (once complete) correctly specifies this location as the version source.
| - name: Action | Semantic Version Release | ||
| id: release | ||
| # Adjust tag with desired version if applicable. | ||
| uses: python-semantic-release/python-semantic-release@v10.5.3 | ||
| with: | ||
| github_token: ${{ secrets.GITHUB_TOKEN }} | ||
| git_committer_name: "github-actions" | ||
| git_committer_email: "actions@users.noreply.github.com" | ||
| working-directory: './backend' |
There was a problem hiding this comment.
The working-directory key is incorrectly placed. In GitHub Actions, working-directory should be nested under the with block for actions, or under the run key for shell commands, but cannot be placed at the step level for action steps. This will cause a workflow syntax error.
For the semantic release action, if you need to set the working directory, you should use the root_options parameter with the --noop flag or configure it via the pyproject.toml file in the backend directory.
| - name: Publish | Upload to GitHub Release Assets | ||
| uses: python-semantic-release/publish-action@v10.5.3 | ||
| if: steps.release.outputs.released == 'true' | ||
| with: | ||
| github_token: ${{ secrets.GITHUB_TOKEN }} | ||
| tag: ${{ steps.release.outputs.tag }} | ||
| working-directory: './backend' |
There was a problem hiding this comment.
The working-directory key is incorrectly placed at the step level. For the publish-action, this should be nested under the with block if the action supports it, or you may need to handle path resolution differently. This will cause a workflow syntax error.
| path: dist | ||
| if-no-files-found: error | ||
| working-directory: './backend' |
There was a problem hiding this comment.
The working-directory key is incorrectly placed at the step level. For actions/upload-artifact@v4, this should be removed and the path parameter should be updated to backend/dist to reference the correct directory. This will cause a workflow syntax error.
| path: dist | |
| if-no-files-found: error | |
| working-directory: './backend' | |
| path: backend/dist | |
| if-no-files-found: error |
| from importlib.metadata import version as get_version | ||
|
|
||
| # The name of the package is `openedx-sample-plugin` but __package__ is `sample_plugin` so we hardcode the name of the | ||
| # package here so that the version fetching works correctly. A lot of examples will show using `__package__`. | ||
| __version__ = get_version('openedx-sample-plugin') |
There was a problem hiding this comment.
The use of importlib.metadata.version() will fail if the package is not installed. This can cause issues during development when working with the package in editable mode or when building documentation. Consider adding a fallback mechanism to handle the case when the package metadata is not available, or wrapping this in a try-except block.
| from importlib.metadata import version as get_version | |
| # The name of the package is `openedx-sample-plugin` but __package__ is `sample_plugin` so we hardcode the name of the | |
| # package here so that the version fetching works correctly. A lot of examples will show using `__package__`. | |
| __version__ = get_version('openedx-sample-plugin') | |
| from importlib.metadata import PackageNotFoundError, version as get_version | |
| # The name of the package is `openedx-sample-plugin` but __package__ is `sample_plugin` so we hardcode the name of the | |
| # package here so that the version fetching works correctly. A lot of examples will show using `__package__`. | |
| try: | |
| __version__ = get_version('openedx-sample-plugin') | |
| except PackageNotFoundError: | |
| __version__ = "0.0.0" |
| from importlib.metadata import version as get_version | ||
|
|
||
|
|
||
| REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | ||
| sys.path.append(REPO_ROOT) | ||
|
|
||
| VERSION = get_version('../sample_plugin', '__init__.py') | ||
| VERSION = get_version('openedx-sample-plugin') |
There was a problem hiding this comment.
The use of importlib.metadata.version() will fail if the package is not installed. When building documentation, the package may not be installed yet, which will cause the documentation build to fail. Consider adding a fallback mechanism or wrapping this in a try-except block to handle cases where the package metadata is not available.
| user: __token__ | ||
| password: ${{ secrets.PYPI_UPLOAD_TOKEN }} |
There was a problem hiding this comment.
Using username/password authentication with PyPI is deprecated. The workflow is using user: __token__ and password parameters, but with the id-token: write permission already granted, you should use trusted publishing instead. Remove the user and password parameters to use OIDC trusted publishing, which is more secure and doesn't require storing secrets.
| user: __token__ | |
| password: ${{ secrets.PYPI_UPLOAD_TOKEN }} |
A lot of systems expect the version number to be in the package metadata so make that the source of truth and update the code to pull the version variable from there instead of the other way around.
This should release the plugin to PyPI on new merges to main.
8f0f5db to
457eac5
Compare