Skip to content

Commit 8c3a482

Browse files
Add workflows for release and main branch testing (#35)
* Use absolute URLs for `README.md` media files Replace relative media file paths with absolute URLs from the GitHub repository (raw.githubusercontent) to correctly render media files in external platforms like PyPI. * Standardize package version format to `X.Y.Z` Update the project version from `1.1` to `1.1.0` to align with standard Python package versioning. * Remove unused requirements files to avoid redundancy * Add "Test Main" workflow for main branch testing This workflow tests the main branch across the supported python versions of the project (3.10, 3.11, 3.12) to ensure compatibility and that the main branch is ready for releases. * Extend Python classifiers to align with tested versions * Add release workflow for PyPI publishing and GH release * Bump project version to `1.2.0`
1 parent 94150cc commit 8c3a482

File tree

6 files changed

+239
-20
lines changed

6 files changed

+239
-20
lines changed

.github/workflows/release.yml

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- "[0-9]+.[0-9]+.[0-9]+"
7+
8+
env:
9+
PACKAGE_NAME: "direct-data-driven-mpc"
10+
TAG_NAME: ${{ github.ref_name }}
11+
PYTHON_VERSION: '3.12'
12+
13+
jobs:
14+
verify_tag:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: Checkout
18+
uses: actions/checkout@v4
19+
with:
20+
fetch-depth: 0
21+
22+
- name: Verify tag matches pyproject.toml version
23+
id: release
24+
run: |
25+
TAG_VERSION=$TAG_NAME
26+
PYPROJECT_VERSION=$(sed -nE 's/^version\s*=\s*"([^"]+)"/\1/p' pyproject.toml)
27+
echo "Tag version: $TAG_VERSION"
28+
echo "pyproject.toml version: $PYPROJECT_VERSION"
29+
if [ "$TAG_VERSION" != "$PYPROJECT_VERSION" ]; then
30+
echo "Tag does not match pyproject.toml version."
31+
exit 1
32+
else
33+
echo "Tag matches pyproject.toml version."
34+
fi
35+
36+
- name: Verify tag points to latest main commit
37+
run: |
38+
git fetch origin main
39+
LATEST_MAIN_SHA=$(git rev-parse origin/main)
40+
echo "Tag commit SHA: $GITHUB_SHA"
41+
echo "Latest main commit SHA: $LATEST_MAIN_SHA"
42+
if [ "$GITHUB_SHA" != "$LATEST_MAIN_SHA" ]; then
43+
echo "Tag does not point to the latest main commit."
44+
exit 1
45+
else
46+
echo "Tag points to the latest main commit."
47+
fi
48+
49+
check_pypi:
50+
needs: verify_tag
51+
runs-on: ubuntu-latest
52+
steps:
53+
- name: Fetch information from PyPI
54+
run: |
55+
response=$(curl -s https://pypi.org/pypi/${{ env.PACKAGE_NAME }}/json || echo "{}")
56+
latest_previous_version=$(echo $response | jq --raw-output "select(.releases != null) | .releases | keys_unsorted | last")
57+
if [ -z "$latest_previous_version" ]; then
58+
echo "Package not found on PyPI."
59+
latest_previous_version="0.0.0"
60+
fi
61+
echo "Latest version on PyPI: $latest_previous_version"
62+
echo "latest_previous_version=$latest_previous_version" >> $GITHUB_ENV
63+
64+
- name: Compare versions and exit if not newer
65+
run: |
66+
NEW_VERSION=$TAG_NAME
67+
LATEST_VERSION=$latest_previous_version
68+
HIGHEST_VERSION=$(printf '%s\n' "$LATEST_VERSION" "$NEW_VERSION" | sort -rV | head -n 1)
69+
if [[ "$HIGHEST_VERSION" != "$NEW_VERSION" || "$NEW_VERSION" = "$LATEST_VERSION" ]]; then
70+
echo "The new version $NEW_VERSION is not greater than the latest version $LATEST_VERSION on PyPI."
71+
exit 1
72+
else
73+
echo "The new version $NEW_VERSION is greater than the latest version $LATEST_VERSION on PyPI."
74+
fi
75+
76+
build:
77+
needs: check_pypi
78+
runs-on: ubuntu-latest
79+
steps:
80+
- name: Checkout
81+
uses: actions/checkout@v4
82+
83+
- name: Set up Python
84+
uses: actions/setup-python@v5
85+
with:
86+
python-version: ${{ env.PYTHON_VERSION }}
87+
88+
- name: Upgrade pip and install build dependencies
89+
run: |
90+
python -m pip install --upgrade pip
91+
pip install build
92+
93+
- name: Install project package in editable mode
94+
run: |
95+
pip install -e .
96+
97+
- name: Build source and wheel distribution
98+
run: |
99+
python -m build
100+
101+
- name: Upload artifacts
102+
uses: actions/upload-artifact@v4
103+
with:
104+
name: dist
105+
path: dist/
106+
107+
pypi_publish:
108+
needs: build
109+
runs-on: ubuntu-latest
110+
environment:
111+
name: release
112+
permissions:
113+
id-token: write
114+
steps:
115+
- name: Download artifacts
116+
uses: actions/download-artifact@v4
117+
with:
118+
name: dist
119+
path: dist/
120+
121+
- name: Publish distribution to PyPI
122+
uses: pypa/gh-action-pypi-publish@release/v1
123+
124+
github_release:
125+
needs: pypi_publish
126+
runs-on: ubuntu-latest
127+
permissions:
128+
contents: write
129+
steps:
130+
- name: Checkout
131+
uses: actions/checkout@v4
132+
with:
133+
fetch-depth: 0
134+
135+
- name: Download artifacts
136+
uses: actions/download-artifact@v4
137+
with:
138+
name: dist
139+
path: dist/
140+
141+
- name: Create GitHub Release
142+
uses: softprops/action-gh-release@v2
143+
with:
144+
generate_release_notes: true
145+
files: dist/*

.github/workflows/test_main.yml

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
---
2+
name: Test Main
3+
concurrency:
4+
group: ${{ github.workflow }}-${{ github.ref_name }}
5+
cancel-in-progress: true
6+
7+
on:
8+
push:
9+
branches: ["main"]
10+
11+
jobs:
12+
unit_tests:
13+
runs-on: ubuntu-latest
14+
strategy:
15+
matrix:
16+
python_container:
17+
- version: "3.10"
18+
image: "python:3.10-slim-bullseye"
19+
- version: "3.11"
20+
image: "python:3.11-slim-bullseye"
21+
- version: "3.12"
22+
image: "python:3.12-slim-bullseye"
23+
container:
24+
image: ${{ matrix.python_container.image }}
25+
steps:
26+
- name: Checkout
27+
uses: actions/checkout@v4
28+
29+
- name: Install ffmpeg
30+
run: |
31+
apt-get update && \
32+
until apt-get install -y ffmpeg; do \
33+
echo "Retrying ffmpeg installation..."; \
34+
sleep 5; \
35+
done
36+
37+
- name: Install dependencies
38+
run: |
39+
python -m pip install --upgrade pip
40+
pip install --default-timeout=60 --retries=5 -r requirements-ci.txt
41+
42+
- name: Install project package in editable mode
43+
run: |
44+
pip install -e .
45+
46+
- name: Run unit tests
47+
run: |
48+
pytest --maxfail=2 --disable-warnings -m "not integration"
49+
50+
integration_tests:
51+
runs-on: ubuntu-latest
52+
strategy:
53+
matrix:
54+
python_container:
55+
- version: "3.10"
56+
image: "python:3.10-slim-bullseye"
57+
- version: "3.11"
58+
image: "python:3.11-slim-bullseye"
59+
- version: "3.12"
60+
image: "python:3.12-slim-bullseye"
61+
test_type: [lti_integration, nonlinear_integration]
62+
container:
63+
image: ${{ matrix.python_container.image }}
64+
steps:
65+
- name: Checkout
66+
uses: actions/checkout@v4
67+
68+
- name: Install ffmpeg
69+
run: |
70+
apt-get update && \
71+
until apt-get install -y ffmpeg; do \
72+
echo "Retrying ffmpeg installation..."; \
73+
sleep 5; \
74+
done
75+
76+
- name: Install dependencies
77+
run: |
78+
python -m pip install --upgrade pip
79+
pip install --default-timeout=60 --retries=5 -r requirements-ci.txt
80+
81+
- name: Install project package in editable mode
82+
run: |
83+
pip install -e .
84+
85+
- name: Run integration test - ${{ matrix.test_type }}
86+
run: |
87+
pytest --disable-warnings -m "${{ matrix.test_type }}"

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
<th width="50%">Nonlinear Data-Driven MPC</th>
1717
</tr>
1818
<tr>
19-
<td><img src="docs/resources/robust_dd_mpc_anim.gif" alt="Robust Data-Driven MPC Animation"></td>
20-
<td><img src="docs/resources/nonlinear_dd_mpc_anim.gif" alt="Nonlinear Data-Driven MPC Animation"></td>
19+
<td><img src="https://raw.githubusercontent.com/pavelacamposp/direct-data-driven-mpc/main/docs/resources/robust_dd_mpc_anim.gif" alt="Robust Data-Driven MPC Animation"></td>
20+
<td><img src="https://raw.githubusercontent.com/pavelacamposp/direct-data-driven-mpc/main/docs/resources/nonlinear_dd_mpc_anim.gif" alt="Nonlinear Data-Driven MPC Animation"></td>
2121
</tr>
2222
<tr>
2323
<td>Robust controller applied to an LTI system.</td>
@@ -190,7 +190,7 @@ The figures below show the expected output from executing these scripts. The gra
190190
191191
|LTI Data-Driven MPC|Nonlinear Data-Driven MPC|
192192
|-|-|
193-
|<img src="docs/resources/robust_dd_mpc_reproduction.png" alt="Robust Data-Driven MPC Animation">|<img src="docs/resources/nonlinear_dd_mpc_reproduction.png" alt="Nonlinear Data-Driven MPC Animation">|
193+
|<img src="https://raw.githubusercontent.com/pavelacamposp/direct-data-driven-mpc/main/docs/resources/robust_dd_mpc_reproduction.png" alt="Robust Data-Driven MPC Animation">|<img src="https://raw.githubusercontent.com/pavelacamposp/direct-data-driven-mpc/main/docs/resources/nonlinear_dd_mpc_reproduction.png" alt="Nonlinear Data-Driven MPC Animation">|
194194
|Reproduction of results from [[1]](#1)|Reproduction of results from [[2]](#2)|
195195
196196
## Code Structure

pyproject.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "direct-data-driven-mpc"
7-
version = "1.1"
7+
version = "1.2.0"
88
authors = [
99
{ name = "Pável A. Campos-Peña", email = "pcamposp@uni.pe" }
1010
]
@@ -32,6 +32,9 @@ keywords = [
3232
]
3333
classifiers = [
3434
"Programming Language :: Python :: 3",
35+
"Programming Language :: Python :: 3.10",
36+
"Programming Language :: Python :: 3.11",
37+
"Programming Language :: Python :: 3.12",
3538
"Operating System :: OS Independent",
3639
]
3740

requirements-dev.txt

Lines changed: 0 additions & 9 deletions
This file was deleted.

requirements.txt

Lines changed: 0 additions & 7 deletions
This file was deleted.

0 commit comments

Comments
 (0)