From 70798c12d5b257b5eb41995348b9efda1bca513e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Vieira?= <5628858+vvvieira@users.noreply.github.com> Date: Thu, 3 Apr 2025 16:01:19 +0100 Subject: [PATCH 01/29] CNF: add base workflows --- .github/workflows/main.yml | 101 +++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 .github/workflows/main.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..76fcafc --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,101 @@ +# .github/workflows/main.yml +name: CI Pipeline + +on: + push: + branches: + - main # Or your main development branch + pull_request: + branches: + - main # Or your main development branch + +env: + CORE_TEST_FOLDER: "./tests/core" + EXTRAS_TEST_FOLDER: "./tests/extras" + +jobs: + docker-build: + # This job corresponds to the .docker-build job from your included template. + # You'll need to implement the Docker build logic here. Assuming a multi-stage build. + runs-on: ubuntu-latest # Adjust runner as needed + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + # --- The following steps need to be tailored to your multi-stage Docker build --- + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Login to the Container Registry (if needed) + # If your registry requires login, uncomment and configure this step + # uses: docker/login-action@v2 + # with: + # registry: your-registry.example.com + # username: ${{ secrets.DOCKER_USERNAME }} + # password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Build and push Docker image + uses: docker/build-push-action@v3 + with: + context: . + push: false # Set to true to push the image + tags: ${{ github.registry }}/${{ github.repository }}:${{ github.sha }} #example for a tag + build-args: | + TARGET: dev + EXTRA: dfba,test + + + test: + needs: docker-build + runs-on: ubuntu-latest + strategy: + matrix: + test_type: + - no-extras + - with-dfba-extra + include: + - test_type: no-extras + test_path: ${{ env.CORE_TEST_FOLDER }} + extra_dependencies: "" # No extra dependencies for this test type + - test_type: with-dfba-extra + test_path: ${{ env.EXTRAS_TEST_FOLDER }} + extra_dependencies: "--with dfba" # List any extra dependencies here + + container: + image: ${{ github.registry }}/${{ github.repository }}:${{ github.sha }} #this will need to be adjusted, depending on the context of the docker images + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up caching + uses: actions/cache@v3 + with: + path: ~/.uv/cache + key: ${{ runner.os }}-${{ github.ref }}-${{ github.sha }}-${{ matrix.test_type }} + restore-keys: | + ${{ runner.os }}-${{ github.ref }}-${{ github.sha }}- + ${{ runner.os }}-${{ github.ref }}- + ${{ runner.os }}- + + - name: Install dependencies and run tests + run: | + uv run ${{ matrix.extra_dependencies }} --with pytest --with pytest-cov coverage run --source ./src -m pytest ${{ matrix.test_path }} --junitxml=test_report.xml + + - name: Generate coverage report + run: | + coverage xml + coverage report + + - name: Upload test results + uses: actions/upload-artifact@v3 + with: + name: test-report-${{ matrix.test_type }} + path: test_report.xml + + - name: Upload coverage report + uses: actions/upload-artifact@v3 + with: + name: coverage-report-${{ matrix.test_type }} + path: coverage.xml From a3028d6440fdaea3e69dbe206ff09eb033ad7452 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Vieira?= Date: Thu, 3 Apr 2025 15:11:12 +0000 Subject: [PATCH 02/29] CNF: use previous image --- Dockerfile | 71 +++--------------------------------------------------- 1 file changed, 4 insertions(+), 67 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8025df9..87faff4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,70 +1,8 @@ -FROM debian:bookworm-slim as builder - -ARG SUNDIALS_VERSION="5.0.0" - -ENV SUNDIALS="/opt/sundials" - -WORKDIR / - -# install debian essentials for building dependencies -RUN apt-get update && apt-get install -y --no-install-recommends \ - gcc \ - cmake \ - build-essential \ - curl \ - gnupg2 \ - ca-certificates \ - && update-ca-certificates \ - && rm -rf /var/lib/apt/lists/* - -RUN curl -L -O "https://github.com/LLNL/sundials/releases/download/v${SUNDIALS_VERSION}/sundials-${SUNDIALS_VERSION}.tar.gz" && \ - tar -xzf sundials-${SUNDIALS_VERSION}.tar.gz && \ - mkdir ${SUNDIALS} && \ - mkdir ${SUNDIALS}/install && \ - mkdir ${SUNDIALS}/build && \ - cd ${SUNDIALS}/build && \ - cmake -DCMAKE_INSTALL_PREFIX=${SUNDIALS}/install \ - -DEXAMPLES_INSTALL_PATH=${SUNDIALS}/install/examples \ - /sundials-${SUNDIALS_VERSION} && \ - make && \ - make install - -# SUNDIALS container image -FROM python:3.10-slim-bookworm as dev - -ARG GLPK_VERSION="4.65" -ENV SUNDIALS="/opt/sundials" - -COPY --from=builder ${SUNDIALS}/install ${SUNDIALS} - -RUN apt-get update && apt-get install -y --no-install-recommends \ - curl \ - pybind11-dev \ - build-essential \ - gcc \ - gnupg2 \ - cmake \ - gfortran \ - libgmp-dev \ - python-dev-is-python3 \ - libglpk-dev && \ - rm -rf /var/lib/apt/lists/* - -# GLPK -# Download the specified distribution, verify it and install -RUN curl -L -O "ftp://ftp.gnu.org/gnu/glpk/glpk-${GLPK_VERSION}.tar.gz" && \ - curl -L -O "ftp://ftp.gnu.org/gnu/glpk/glpk-${GLPK_VERSION}.tar.gz.sig" && \ - gpg --keyserver keyserver.ubuntu.com --recv-keys 5981E818 && \ - gpg --verify "glpk-${GLPK_VERSION}.tar.gz.sig" && \ - tar -xzf "glpk-${GLPK_VERSION}.tar.gz" && \ - cd "glpk-${GLPK_VERSION}" && \ - ./configure --with-gmp && \ - make && \ - make install && \ - cd .. && \ - rm -rf "glpk-${GLPK_VERSION}"* - +ARG SUNDIALS_VERSION=5.1.0 +ARG GLPK_VERSION=4.65 +ARG EXTRAS="dfba" +FROM ghcr.io/amyris/sundials-glpk-pybind:sundials-${SUNDIALS_VERSION}-glpk-${GLPK_VERSION} COPY --from=ghcr.io/astral-sh/uv:0.6.11 /uv /uvx /bin/ ENV UV_COMPILE_BYTECODE=1 @@ -74,7 +12,6 @@ WORKDIR /app COPY pyproject.toml ./ -ARG EXTRAS="dfba" RUN EXTRA_NAMES=$(echo $EXTRAS | sed 's/,/ --extra /g' | sed 's/^/--extra /') RUN echo ${EXTRA_NAMES} From 7513fdddfb2e7323f37b9d362b6c273d4032da4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Vieira?= Date: Thu, 3 Apr 2025 15:16:58 +0000 Subject: [PATCH 03/29] CNF: added tar based image build --- .github/workflows/main.yml | 43 ++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 76fcafc..6f30aca 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -4,14 +4,15 @@ name: CI Pipeline on: push: branches: - - main # Or your main development branch + - main pull_request: branches: - - main # Or your main development branch + - main env: CORE_TEST_FOLDER: "./tests/core" EXTRAS_TEST_FOLDER: "./tests/extras" + IMAGE_NAME: local-test-image:latest # A simple image name, as we're not pushing jobs: docker-build: @@ -27,23 +28,17 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - - name: Login to the Container Registry (if needed) - # If your registry requires login, uncomment and configure this step - # uses: docker/login-action@v2 - # with: - # registry: your-registry.example.com - # username: ${{ secrets.DOCKER_USERNAME }} - # password: ${{ secrets.DOCKER_PASSWORD }} + - name: Build the Docker image + run: docker build -t ${{ env.IMAGE_NAME }} . - - name: Build and push Docker image - uses: docker/build-push-action@v3 + - name: Export the Docker image as a tarball + run: docker save -o image.tar ${{ env.IMAGE_NAME }} + + - name: Upload the Docker image tarball as an artifact + uses: actions/upload-artifact@v3 with: - context: . - push: false # Set to true to push the image - tags: ${{ github.registry }}/${{ github.repository }}:${{ github.sha }} #example for a tag - build-args: | - TARGET: dev - EXTRA: dfba,test + name: docker-image + path: image.tar test: @@ -69,16 +64,14 @@ jobs: - name: Checkout code uses: actions/checkout@v3 - - name: Set up caching - uses: actions/cache@v3 + - name: Download the Docker image tarball + uses: actions/download-artifact@v3 with: - path: ~/.uv/cache - key: ${{ runner.os }}-${{ github.ref }}-${{ github.sha }}-${{ matrix.test_type }} - restore-keys: | - ${{ runner.os }}-${{ github.ref }}-${{ github.sha }}- - ${{ runner.os }}-${{ github.ref }}- - ${{ runner.os }}- + name: docker-image + path: . + - name: Load the Docker image + run: docker load -i image.tar - name: Install dependencies and run tests run: | uv run ${{ matrix.extra_dependencies }} --with pytest --with pytest-cov coverage run --source ./src -m pytest ${{ matrix.test_path }} --junitxml=test_report.xml From f66bb33f2afad2e35228943280d3bb77e9af6438 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Vieira?= Date: Thu, 3 Apr 2025 15:22:05 +0000 Subject: [PATCH 04/29] CNF: pinned debian, changed pull request workflow --- .github/workflows/main.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6f30aca..4da350d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -6,8 +6,9 @@ on: branches: - main pull_request: - branches: - - main + # This will trigger the workflow on any pull request, regardless of the target branch. + types: [opened, synchronize, reopened] + workflow_dispatch: # Allow manual triggering of the workflow env: CORE_TEST_FOLDER: "./tests/core" @@ -18,7 +19,7 @@ jobs: docker-build: # This job corresponds to the .docker-build job from your included template. # You'll need to implement the Docker build logic here. Assuming a multi-stage build. - runs-on: ubuntu-latest # Adjust runner as needed + runs-on: debian-bookworm # Adjust runner as needed steps: - name: Checkout code From 923926922aaf7769e985406adfbbaa0f0c6f71bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Vieira?= Date: Thu, 3 Apr 2025 15:36:24 +0000 Subject: [PATCH 05/29] CNF: fixed env var referencing --- .github/workflows/main.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4da350d..4fe3218 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -30,10 +30,10 @@ jobs: uses: docker/setup-buildx-action@v2 - name: Build the Docker image - run: docker build -t ${{ env.IMAGE_NAME }} . + run: docker build -t $IMAGE_NAME . - name: Export the Docker image as a tarball - run: docker save -o image.tar ${{ env.IMAGE_NAME }} + run: docker save -o image.tar $IMAGE_NAME - name: Upload the Docker image tarball as an artifact uses: actions/upload-artifact@v3 @@ -52,10 +52,10 @@ jobs: - with-dfba-extra include: - test_type: no-extras - test_path: ${{ env.CORE_TEST_FOLDER }} + test_path: $CORE_TEST_FOLDER extra_dependencies: "" # No extra dependencies for this test type - test_type: with-dfba-extra - test_path: ${{ env.EXTRAS_TEST_FOLDER }} + test_path: $EXTRAS_TEST_FOLDER extra_dependencies: "--with dfba" # List any extra dependencies here container: From dce269cd708201c9a564ae2d1d61722131d2436f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Vieira?= Date: Thu, 3 Apr 2025 15:44:25 +0000 Subject: [PATCH 06/29] CNF: updated os for runners --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4fe3218..1d42032 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -19,7 +19,7 @@ jobs: docker-build: # This job corresponds to the .docker-build job from your included template. # You'll need to implement the Docker build logic here. Assuming a multi-stage build. - runs-on: debian-bookworm # Adjust runner as needed + runs-on: ubuntu-24.04 # Adjust runner as needed steps: - name: Checkout code @@ -44,7 +44,7 @@ jobs: test: needs: docker-build - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 strategy: matrix: test_type: From 82ca4ba2c46ce5e8951410904180d74c182e1abe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Vieira?= Date: Thu, 3 Apr 2025 21:34:46 +0000 Subject: [PATCH 07/29] CNF: update upload version --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1d42032..76c2016 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -36,7 +36,7 @@ jobs: run: docker save -o image.tar $IMAGE_NAME - name: Upload the Docker image tarball as an artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: docker-image path: image.tar From 1d63e6ff7c9b38db13bd57aff4905ec2fc87c2d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Vieira?= Date: Thu, 3 Apr 2025 21:51:52 +0000 Subject: [PATCH 08/29] CNF: added dev multistage --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 87faff4..3ae5b09 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ ARG SUNDIALS_VERSION=5.1.0 ARG GLPK_VERSION=4.65 ARG EXTRAS="dfba" -FROM ghcr.io/amyris/sundials-glpk-pybind:sundials-${SUNDIALS_VERSION}-glpk-${GLPK_VERSION} +FROM ghcr.io/amyris/sundials-glpk-pybind:sundials-${SUNDIALS_VERSION}-glpk-${GLPK_VERSION} as dev COPY --from=ghcr.io/astral-sh/uv:0.6.11 /uv /uvx /bin/ ENV UV_COMPILE_BYTECODE=1 From b3fe7b49c11b9c3d659825710e14058d3f41c34c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Vieira?= Date: Thu, 3 Apr 2025 21:57:04 +0000 Subject: [PATCH 09/29] CNF: updated action versions --- .github/workflows/main.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 76c2016..34e20d2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -66,7 +66,7 @@ jobs: uses: actions/checkout@v3 - name: Download the Docker image tarball - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: docker-image path: . @@ -83,13 +83,13 @@ jobs: coverage report - name: Upload test results - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: test-report-${{ matrix.test_type }} path: test_report.xml - name: Upload coverage report - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: coverage-report-${{ matrix.test_type }} path: coverage.xml From 3131f58e78a382a34c7007d28c8087c1744f8be9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Vieira?= Date: Fri, 4 Apr 2025 09:27:50 +0000 Subject: [PATCH 10/29] CNF: try new config --- .github/workflows/main.yml | 108 ++++++++++--------------------------- 1 file changed, 28 insertions(+), 80 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 34e20d2..e718580 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,95 +1,43 @@ -# .github/workflows/main.yml -name: CI Pipeline +name: CI - Run Unit Tests in Docker on: push: + branches: [ main ] # Or your default branch + # Trigger on pull requests targeting the main branch + pull_request: branches: - main - pull_request: - # This will trigger the workflow on any pull request, regardless of the target branch. - types: [opened, synchronize, reopened] - workflow_dispatch: # Allow manual triggering of the workflow - -env: - CORE_TEST_FOLDER: "./tests/core" - EXTRAS_TEST_FOLDER: "./tests/extras" - IMAGE_NAME: local-test-image:latest # A simple image name, as we're not pushing jobs: - docker-build: - # This job corresponds to the .docker-build job from your included template. - # You'll need to implement the Docker build logic here. Assuming a multi-stage build. - runs-on: ubuntu-24.04 # Adjust runner as needed - - steps: - - name: Checkout code - uses: actions/checkout@v3 - - # --- The following steps need to be tailored to your multi-stage Docker build --- - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Build the Docker image - run: docker build -t $IMAGE_NAME . - - - name: Export the Docker image as a tarball - run: docker save -o image.tar $IMAGE_NAME - - - name: Upload the Docker image tarball as an artifact - uses: actions/upload-artifact@v4 - with: - name: docker-image - path: image.tar - - test: - needs: docker-build - runs-on: ubuntu-24.04 - strategy: - matrix: - test_type: - - no-extras - - with-dfba-extra - include: - - test_type: no-extras - test_path: $CORE_TEST_FOLDER - extra_dependencies: "" # No extra dependencies for this test type - - test_type: with-dfba-extra - test_path: $EXTRAS_TEST_FOLDER - extra_dependencies: "--with dfba" # List any extra dependencies here - - container: - image: ${{ github.registry }}/${{ github.repository }}:${{ github.sha }} #this will need to be adjusted, depending on the context of the docker images + runs-on: ubuntu-latest # Standard runner with Docker pre-installed steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - - name: Download the Docker image tarball - uses: actions/download-artifact@v4 - with: - name: docker-image - path: . - - - name: Load the Docker image - run: docker load -i image.tar - - name: Install dependencies and run tests + - name: Build Docker image for testing run: | - uv run ${{ matrix.extra_dependencies }} --with pytest --with pytest-cov coverage run --source ./src -m pytest ${{ matrix.test_path }} --junitxml=test_report.xml - - - name: Generate coverage report + docker build \ + --tag my-test-image:latest \ + --file Dockerfile . + # Notes: + # --tag my-test-image:latest : Gives the image a local name we can reference. + # --file path/to/your/Dockerfile : IMPORTANT: Replace with the actual path to your Dockerfile. + # . : Specifies the build context (usually the repository root). + + - name: Run tests with dFBA extra run: | - coverage xml - coverage report + docker run --rm \ + -v "$(pwd):/app" \ + -w /app \ + my-test-image:latest \ + uv run --with dfba --with pytest --with pytest-cov coverage run --source ./src -m pytest ./tests/extras --junitxml=test_report.xml - - name: Upload test results - uses: actions/upload-artifact@v4 - with: - name: test-report-${{ matrix.test_type }} - path: test_report.xml - - - name: Upload coverage report - uses: actions/upload-artifact@v4 - with: - name: coverage-report-${{ matrix.test_type }} - path: coverage.xml + - name: Run tests without dFBA extra + run: | + docker run --rm \ + -v "$(pwd):/app" \ + -w /app \ + my-test-image:latest \ + uv run --with pytest --with pytest-cov coverage run --source ./src -m pytest ./tests/core --junitxml=test_report.xml From c506e540b2340e2fa3a0b5ec00f073fbc1c92018 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Vieira?= Date: Fri, 4 Apr 2025 09:33:25 +0000 Subject: [PATCH 11/29] CNF: target dev stage --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e718580..3d095e0 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -19,6 +19,7 @@ jobs: - name: Build Docker image for testing run: | docker build \ + --target dev \ --tag my-test-image:latest \ --file Dockerfile . # Notes: From 1b5d16f231bf8d4bf36ddb24e39df7a510ece1d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Vieira?= Date: Fri, 4 Apr 2025 09:46:04 +0000 Subject: [PATCH 12/29] CNF: added coverage --- .github/workflows/main.yml | 64 ++++++++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 13 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3d095e0..e582d0f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,16 +1,14 @@ -name: CI - Run Unit Tests in Docker +name: CI - Run Unit Tests in Docker with Coverage on: push: - branches: [ main ] # Or your default branch - # Trigger on pull requests targeting the main branch + branches: [ main ] pull_request: - branches: - - main + branches: [ main ] jobs: test: - runs-on: ubuntu-latest # Standard runner with Docker pre-installed + runs-on: ubuntu-latest steps: - name: Checkout code @@ -21,24 +19,64 @@ jobs: docker build \ --target dev \ --tag my-test-image:latest \ - --file Dockerfile . - # Notes: - # --tag my-test-image:latest : Gives the image a local name we can reference. - # --file path/to/your/Dockerfile : IMPORTANT: Replace with the actual path to your Dockerfile. - # . : Specifies the build context (usually the repository root). + --file Dockerfile . # Assuming Dockerfile is at the root - name: Run tests with dFBA extra run: | + # Runs coverage collection via 'uv run' using --with pytest-cov. + # Uses --parallel-mode for coverage data. + # Generates uniquely named JUnit report. docker run --rm \ -v "$(pwd):/app" \ -w /app \ my-test-image:latest \ - uv run --with dfba --with pytest --with pytest-cov coverage run --source ./src -m pytest ./tests/extras --junitxml=test_report.xml + uv run --with dfba --with pytest --with pytest-cov coverage run --parallel-mode -m pytest ./tests/extras --junitxml=test-report-dfba.xml - name: Run tests without dFBA extra run: | + # Runs coverage collection via 'uv run' using --with pytest-cov. + # Uses --parallel-mode for coverage data. + # Generates uniquely named JUnit report. docker run --rm \ -v "$(pwd):/app" \ -w /app \ my-test-image:latest \ - uv run --with pytest --with pytest-cov coverage run --source ./src -m pytest ./tests/core --junitxml=test_report.xml + uv run --with pytest --with pytest-cov coverage run --parallel-mode -m pytest ./tests/core --junitxml=test-report-core.xml + + # --- The step below only runs if BOTH test steps above succeeded --- + + - name: Combine and Report Coverage + # Combines parallel data, generates console summary and HTML report in one step. + if: success() + run: | + echo "Combining coverage data..." + docker run --rm \ + --user "$(id -u):$(id -g)" \ + -v "$(pwd):/app" \ + -w /app \ + my-test-image:latest \ + coverage combine # Assumes config in pyproject.toml/.coveragerc + + echo "Generating coverage summary..." + docker run --rm \ + --user "$(id -u):$(id -g)" \ + -v "$(pwd):/app" \ + -w /app \ + my-test-image:latest \ + coverage report -m # Add --fail-under=X here if needed + + echo "Generating HTML coverage report..." + docker run --rm \ + --user "$(id -u):$(id -g)" \ + -v "$(pwd):/app" \ + -w /app \ + my-test-image:latest \ + coverage html -d htmlcov # Generates report in 'htmlcov' directory + + - name: Upload HTML coverage report artifact + if: success() # Runs only if the previous steps (including reporting) succeeded + uses: actions/upload-artifact@v4 + with: + name: coverage-report-html + path: htmlcov/ # Upload the generated HTML directory + retention-days: 7 From bd8352d37806ee5012e9047b1b175ff4a4b59ae0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Vieira?= Date: Fri, 4 Apr 2025 09:53:23 +0000 Subject: [PATCH 13/29] CNF: only include source files for coverage --- .github/workflows/main.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e582d0f..7ef90ea 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -55,7 +55,7 @@ jobs: -v "$(pwd):/app" \ -w /app \ my-test-image:latest \ - coverage combine # Assumes config in pyproject.toml/.coveragerc + coverage --source ./src combine # Assumes config in pyproject.toml/.coveragerc echo "Generating coverage summary..." docker run --rm \ @@ -63,7 +63,7 @@ jobs: -v "$(pwd):/app" \ -w /app \ my-test-image:latest \ - coverage report -m # Add --fail-under=X here if needed + coverage --source ./src report -m # Add --fail-under=X here if needed echo "Generating HTML coverage report..." docker run --rm \ @@ -71,7 +71,7 @@ jobs: -v "$(pwd):/app" \ -w /app \ my-test-image:latest \ - coverage html -d htmlcov # Generates report in 'htmlcov' directory + coverage --source ./src html -d htmlcov # Generates report in 'htmlcov' directory - name: Upload HTML coverage report artifact if: success() # Runs only if the previous steps (including reporting) succeeded From 0b9b8bcefa24c01cee326d514a8f5cfb1a834860 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Vieira?= Date: Fri, 4 Apr 2025 09:57:45 +0000 Subject: [PATCH 14/29] CNF: added source to the correct place --- .github/workflows/main.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7ef90ea..ed9b3ca 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -30,7 +30,7 @@ jobs: -v "$(pwd):/app" \ -w /app \ my-test-image:latest \ - uv run --with dfba --with pytest --with pytest-cov coverage run --parallel-mode -m pytest ./tests/extras --junitxml=test-report-dfba.xml + uv run --with dfba --with pytest --with pytest-cov coverage run --parallel-mode --source ./src/simulib -m pytest ./tests/extras --junitxml=test-report-dfba.xml - name: Run tests without dFBA extra run: | @@ -41,7 +41,7 @@ jobs: -v "$(pwd):/app" \ -w /app \ my-test-image:latest \ - uv run --with pytest --with pytest-cov coverage run --parallel-mode -m pytest ./tests/core --junitxml=test-report-core.xml + uv run --with pytest --with pytest-cov coverage run --parallel-mode --source ./src/simulib -m pytest ./tests/core --junitxml=test-report-core.xml # --- The step below only runs if BOTH test steps above succeeded --- @@ -55,7 +55,7 @@ jobs: -v "$(pwd):/app" \ -w /app \ my-test-image:latest \ - coverage --source ./src combine # Assumes config in pyproject.toml/.coveragerc + coverage combine # Assumes config in pyproject.toml/.coveragerc echo "Generating coverage summary..." docker run --rm \ @@ -63,7 +63,7 @@ jobs: -v "$(pwd):/app" \ -w /app \ my-test-image:latest \ - coverage --source ./src report -m # Add --fail-under=X here if needed + coverage report -m # Add --fail-under=X here if needed echo "Generating HTML coverage report..." docker run --rm \ @@ -71,7 +71,7 @@ jobs: -v "$(pwd):/app" \ -w /app \ my-test-image:latest \ - coverage --source ./src html -d htmlcov # Generates report in 'htmlcov' directory + coverage html -d htmlcov # Generates report in 'htmlcov' directory - name: Upload HTML coverage report artifact if: success() # Runs only if the previous steps (including reporting) succeeded From cbd1229b5f1c09ec98c5df6551cb60d8baf68a7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Vieira?= Date: Fri, 4 Apr 2025 10:06:22 +0000 Subject: [PATCH 15/29] CNF: add PR comment and update coverage report toml settings --- .github/workflows/main.yml | 68 ++++++++++++++++++++++++-------------- pyproject.toml | 20 +++++++++++ 2 files changed, 64 insertions(+), 24 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ed9b3ca..708e6a9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -46,37 +46,57 @@ jobs: # --- The step below only runs if BOTH test steps above succeeded --- - name: Combine and Report Coverage - # Combines parallel data, generates console summary and HTML report in one step. if: success() run: | - echo "Combining coverage data..." - docker run --rm \ - --user "$(id -u):$(id -g)" \ - -v "$(pwd):/app" \ - -w /app \ - my-test-image:latest \ - coverage combine # Assumes config in pyproject.toml/.coveragerc + # Runs combine, report, and html generation in a single container + # Saves the console summary to /app/coverage_summary.txt within the container + # which maps to coverage_summary.txt on the runner host via the volume mount. + docker run --rm \ + --user "$(id -u):$(id -g)" \ + -v "$(pwd):/app" \ + -w /app \ + my-test-image:latest \ + sh -c '\ + echo "Combining coverage data..." && \ + coverage combine && \ + echo "Generating coverage summary..." && \ + coverage report -m > /app/coverage_summary.txt && \ + echo "Generating HTML coverage report..." && \ + coverage html -d htmlcov \ + ' + # Also echo the summary to the main job log for easy viewing there + echo "--- Coverage Summary ---" + cat coverage_summary.txt + echo "------------------------" - echo "Generating coverage summary..." - docker run --rm \ - --user "$(id -u):$(id -g)" \ - -v "$(pwd):/app" \ - -w /app \ - my-test-image:latest \ - coverage report -m # Add --fail-under=X here if needed + - name: Post Coverage Comment to PR + # Only run this step if: + # 1. Previous steps succeeded + # 2. The event that triggered the workflow is a 'pull_request' + if: success() && github.event_name == 'pull_request' + env: + # The GITHUB_TOKEN is automatically available to the runner + # We pass it explicitly for the gh cli command + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + # Create the comment body in a temporary file + echo '### :test_tube: Coverage Report' > coverage_comment.md + echo '' >> coverage_comment.md + echo '```text' >> coverage_comment.md + # Append the captured summary from the file + cat coverage_summary.txt >> coverage_comment.md + echo '' >> coverage_comment.md # Ensure newline before closing fence + echo '```' >> coverage_comment.md - echo "Generating HTML coverage report..." - docker run --rm \ - --user "$(id -u):$(id -g)" \ - -v "$(pwd):/app" \ - -w /app \ - my-test-image:latest \ - coverage html -d htmlcov # Generates report in 'htmlcov' directory + # Use GitHub CLI to post the comment from the file to the PR + # github.event.pull_request.number is available in pull_request events + gh pr comment ${{ github.event.pull_request.number }} --body-file coverage_comment.md - name: Upload HTML coverage report artifact - if: success() # Runs only if the previous steps (including reporting) succeeded + # Keep this running conditionally on success + if: success() uses: actions/upload-artifact@v4 with: name: coverage-report-html - path: htmlcov/ # Upload the generated HTML directory + path: htmlcov/ retention-days: 7 diff --git a/pyproject.toml b/pyproject.toml index 92fd309..6a52987 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -79,3 +79,23 @@ requires = [ ] build-backend = "setuptools.build_meta" +[tool.coverage.run] +source = ["src"] # List format often used here +parallel = true +branch = true +# omit = ["src/__init__.py", "src/config/*"] # Optional + +[tool.coverage.report] +show_missing = true +# fail_under = 90 # Optional +# exclude_lines = [ # Optional +# "pragma: no cover", +# "raise NotImplementedError", +# "if __name__ == .__main__.:", +# ] + +[tool.coverage.html] +directory = "htmlcov" + +[tool.coverage.xml] +# output = "coverage.xml" # Optional From 00b81ba8c4fbff1ad5fcb5f654b3d38a9ab5d53a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Vieira?= Date: Fri, 4 Apr 2025 10:07:07 +0000 Subject: [PATCH 16/29] CNF: call with uv --- .github/workflows/main.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 708e6a9..06007f8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -30,7 +30,7 @@ jobs: -v "$(pwd):/app" \ -w /app \ my-test-image:latest \ - uv run --with dfba --with pytest --with pytest-cov coverage run --parallel-mode --source ./src/simulib -m pytest ./tests/extras --junitxml=test-report-dfba.xml + uv run --with dfba --with pytest --with pytest-cov coverage run --parallel-mode -m pytest ./tests/extras --junitxml=test-report-dfba.xml - name: Run tests without dFBA extra run: | @@ -41,7 +41,7 @@ jobs: -v "$(pwd):/app" \ -w /app \ my-test-image:latest \ - uv run --with pytest --with pytest-cov coverage run --parallel-mode --source ./src/simulib -m pytest ./tests/core --junitxml=test-report-core.xml + uv run --with pytest --with pytest-cov coverage run --parallel-mode -m pytest ./tests/core --junitxml=test-report-core.xml # --- The step below only runs if BOTH test steps above succeeded --- @@ -58,11 +58,11 @@ jobs: my-test-image:latest \ sh -c '\ echo "Combining coverage data..." && \ - coverage combine && \ + uv run --with pytest --with pytest-cov coverage combine && \ echo "Generating coverage summary..." && \ - coverage report -m > /app/coverage_summary.txt && \ + uv run --with pytest --with pytest-cov coverage report -m > /app/coverage_summary.txt && \ echo "Generating HTML coverage report..." && \ - coverage html -d htmlcov \ + uv run --with pytest --with pytest-cov coverage html -d htmlcov \ ' # Also echo the summary to the main job log for easy viewing there echo "--- Coverage Summary ---" From 156c1981a5d1be326ef66efa67f688c975f0999e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Vieira?= Date: Fri, 4 Apr 2025 10:08:56 +0000 Subject: [PATCH 17/29] CNF: enable caching --- .github/workflows/main.yml | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 06007f8..552ed1f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -14,12 +14,23 @@ jobs: - name: Checkout code uses: actions/checkout@v4 - - name: Build Docker image for testing - run: | - docker build \ - --target dev \ - --tag my-test-image:latest \ - --file Dockerfile . # Assuming Dockerfile is at the root + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build Docker image with Cache + uses: docker/build-push-action@v5 + with: + context: . + file: ./Dockerfile # Assuming Dockerfile is at the root + # Build the 'dev' target stage + target: dev + # Tag the image locally so subsequent steps can use it + tags: my-test-image:latest + # IMPORTANT: Load the image into the local Docker daemon + load: true + # Enable layer caching using GitHub Actions cache + cache-from: type=gha + cache-to: type=gha,mode=max - name: Run tests with dFBA extra run: | From 88ed897a0a5aecc60fde4d86269e3689a47b7931 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Vieira?= Date: Fri, 4 Apr 2025 10:10:08 +0000 Subject: [PATCH 18/29] CNF: optimize docker cache and remove uid change --- .github/workflows/main.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 552ed1f..9dd025f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -63,7 +63,6 @@ jobs: # Saves the console summary to /app/coverage_summary.txt within the container # which maps to coverage_summary.txt on the runner host via the volume mount. docker run --rm \ - --user "$(id -u):$(id -g)" \ -v "$(pwd):/app" \ -w /app \ my-test-image:latest \ From fd1ace37d33c06450dcfbe946f27c124d31c3446 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Vieira?= Date: Fri, 4 Apr 2025 10:14:37 +0000 Subject: [PATCH 19/29] CNF: removed upload to artifact storage --- .github/workflows/main.yml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9dd025f..4fdfe86 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -101,12 +101,3 @@ jobs: # Use GitHub CLI to post the comment from the file to the PR # github.event.pull_request.number is available in pull_request events gh pr comment ${{ github.event.pull_request.number }} --body-file coverage_comment.md - - - name: Upload HTML coverage report artifact - # Keep this running conditionally on success - if: success() - uses: actions/upload-artifact@v4 - with: - name: coverage-report-html - path: htmlcov/ - retention-days: 7 From b49a550af958a68bb44a510aae449ee88d29af9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Vieira?= Date: Fri, 4 Apr 2025 10:21:10 +0000 Subject: [PATCH 20/29] CNF: add sticky comment to avoid spam --- .github/workflows/main.yml | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4fdfe86..3fcf692 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -79,25 +79,25 @@ jobs: cat coverage_summary.txt echo "------------------------" - - name: Post Coverage Comment to PR - # Only run this step if: - # 1. Previous steps succeeded - # 2. The event that triggered the workflow is a 'pull_request' + - name: Format Coverage Comment Body + # Prepare the content for the comment in a file + # Only run on successful PR builds if: success() && github.event_name == 'pull_request' - env: - # The GITHUB_TOKEN is automatically available to the runner - # We pass it explicitly for the gh cli command - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - # Create the comment body in a temporary file echo '### :test_tube: Coverage Report' > coverage_comment.md echo '' >> coverage_comment.md echo '```text' >> coverage_comment.md - # Append the captured summary from the file cat coverage_summary.txt >> coverage_comment.md echo '' >> coverage_comment.md # Ensure newline before closing fence echo '```' >> coverage_comment.md - - # Use GitHub CLI to post the comment from the file to the PR - # github.event.pull_request.number is available in pull_request events - gh pr comment ${{ github.event.pull_request.number }} --body-file coverage_comment.md + # Optional: Add a hidden HTML comment marker for extra safety/identification + # echo "" >> coverage_comment.md + + - name: Post or Update Coverage Comment + # Use the sticky comment action + # Only run on successful PR builds + if: success() && github.event_name == 'pull_request' + uses: marocchino/sticky-pull-request-comment@v2 + with: + # Tell the action to read the comment body from the file we just created + path: coverage_comment.md From 5c18b2a24b5d9660e2173a3eeab4073d9acea5d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Vieira?= Date: Fri, 4 Apr 2025 10:46:26 +0000 Subject: [PATCH 21/29] CNF: add build check stage --- .github/workflows/main.yml | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3fcf692..b189eef 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -7,9 +7,32 @@ on: branches: [ main ] jobs: - test: + build_check: + # Run on pull requests to verify the build process + if: github.event_name == 'pull_request' runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + - name: Install uv and build tool + run: | + python -m pip install --upgrade pip uv + uv pip install --system build + + - name: Build package + run: uv run -- python -m build + + - name: List built artifacts + run: ls -l dist/ + + test: + runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 From 6376200ac2497388e49439218d4bf935c2e6015f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Vieira?= Date: Fri, 4 Apr 2025 10:49:23 +0000 Subject: [PATCH 22/29] CNF: hi --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b189eef..e33052d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -7,6 +7,7 @@ on: branches: [ main ] jobs: + build_check: # Run on pull requests to verify the build process if: github.event_name == 'pull_request' From f65d3e89db624b1533aba347582612affdd7d1fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Vieira?= Date: Fri, 4 Apr 2025 14:55:08 +0000 Subject: [PATCH 23/29] CNF: try out 2 publishing stages --- .github/workflows/main.yml | 84 ++++++++++++++++++++++++++------------ 1 file changed, 59 insertions(+), 25 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e33052d..8093e3d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -7,31 +7,6 @@ on: branches: [ main ] jobs: - - build_check: - # Run on pull requests to verify the build process - if: github.event_name == 'pull_request' - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.11' - - - name: Install uv and build tool - run: | - python -m pip install --upgrade pip uv - uv pip install --system build - - - name: Build package - run: uv run -- python -m build - - - name: List built artifacts - run: ls -l dist/ - test: runs-on: ubuntu-latest steps: @@ -125,3 +100,62 @@ jobs: with: # Tell the action to read the comment body from the file we just created path: coverage_comment.md + + publish-to-testpypi: + name: Publish to TestPyPI + needs: test # Depends on test job succeeding + if: github.event_name == 'workflow_dispatch' # Only runs on manual trigger + runs-on: ubuntu-latest + environment: + name: testpypi # Matches Trusted Publisher config on TestPyPI + url: https://test.pypi.org/p/simulib # Replace YOUR_PACKAGE_NAME + permissions: + id-token: write # Needed for Trusted Publishing + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + - name: Install uv + run: curl -LsSf https://astral.sh/uv/install.sh | sh + - name: Install build dependency using uv + run: uv pip install --system --upgrade build + - name: Build package + run: python -m build + - name: Publish package to TestPyPI using uv and Trusted Publishing + run: > + uv publish --repository-url https://test.pypi.org/legacy/ dist/* + # --- End of TestPyPI publish job --- + + publish-to-pypi: + name: Publish to PyPI + needs: publish-to-testpypi # Depends on TestPyPI publish job succeeding + if: github.event_name == 'workflow_dispatch' # Also only runs on manual trigger (implicitly via needs) + runs-on: ubuntu-latest + environment: + name: pypi # MUST MATCH the environment name configured in PyPI Trusted Publishers + url: https://pypi.org/p/simulib # Replace YOUR_PACKAGE_NAME + permissions: + id-token: write # Needed for Trusted Publishing on PyPI + steps: + - name: Checkout code + # Checkout code again for this job's environment + uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + - name: Install uv + run: curl -LsSf https://astral.sh/uv/install.sh | sh + - name: Install build dependency using uv + run: uv pip install --system --upgrade build + - name: Build package + # Re-build the package in this job's environment + run: python -m build + - name: Publish package to PyPI using uv and Trusted Publishing + # No --repository-url needed, uv defaults to PyPI + # Authentication happens via OIDC token automatically + run: uv publish dist/* + # --- End of PyPI publish job --- From 22b8e8f85021dd4bb043b3966274de2bc61d15a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Vieira?= Date: Fri, 4 Apr 2025 15:12:02 +0000 Subject: [PATCH 24/29] CNF: add publish to pypi automatically --- .github/workflows/main.yml | 77 +++++++++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 18 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8093e3d..c8de7ab 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -101,61 +101,102 @@ jobs: # Tell the action to read the comment body from the file we just created path: coverage_comment.md + # --- Automatic TestPyPI Publish Job --- publish-to-testpypi: - name: Publish to TestPyPI + name: Publish Dev Build to TestPyPI needs: test # Depends on test job succeeding - if: github.event_name == 'workflow_dispatch' # Only runs on manual trigger + # Runs ONLY on push events to the main branch (not PRs, not manual triggers) + if: github.ref == 'refs/heads/main' && github.event_name == 'push' && needs.test.result == 'success' runs-on: ubuntu-latest environment: - name: testpypi # Matches Trusted Publisher config on TestPyPI - url: https://test.pypi.org/p/simulib # Replace YOUR_PACKAGE_NAME + name: testpypi + url: https://test.pypi.org/p/simulib # <-- IMPORTANT: Replace simulib with your package name permissions: id-token: write # Needed for Trusted Publishing steps: - name: Checkout code uses: actions/checkout@v4 + with: + fetch-depth: 0 # Fetch all history for versioning if using setuptools_scm later + - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.x' + - name: Install uv run: curl -LsSf https://astral.sh/uv/install.sh | sh - - name: Install build dependency using uv - run: uv pip install --system --upgrade build - - name: Build package + + - name: Install build tools and tomlkit + run: uv pip install --system --upgrade build tomlkit + + - name: Set Development Version + id: set_dev_version + # This script reads pyproject.toml, appends .dev to the version, + # and writes it back. Assumes standard `project.version`. + # Adjust ['project']['version'] if your version is elsewhere (e.g., ['tool']['poetry']['version']) + run: | + import tomlkit, os, sys + run_number = os.environ['GITHUB_RUN_NUMBER'] + toml_path = 'pyproject.toml' + try: + with open(toml_path, 'r') as f: data = tomlkit.parse(f.read()) + # *** ADJUST THIS LINE if your version is not at ['project']['version'] *** + base_version = data['project']['version'] + base_version = base_version.split('.dev')[0].split('+')[0] # Clean existing dev/local parts + dev_version = f"{base_version}.dev{run_number}" + print(f"Setting version for TestPyPI: {dev_version}") + # *** ADJUST THIS LINE if your version is not at ['project']['version'] *** + data['project']['version'] = dev_version + with open(toml_path, 'w') as f: f.write(tomlkit.dumps(data)) + # Set output for potential use in other steps (optional) + echo "dev_version=${dev_version}" >> $GITHUB_OUTPUT + except Exception as e: + print(f"Error updating version in {toml_path}: {e}", file=sys.stderr) + sys.exit(1) + env: + GITHUB_RUN_NUMBER: ${{ github.run_number }} + shell: python # Use python directly to run the script block + + - name: Build package with dev version run: python -m build - - name: Publish package to TestPyPI using uv and Trusted Publishing + + - name: Publish package to TestPyPI run: > uv publish --repository-url https://test.pypi.org/legacy/ dist/* - # --- End of TestPyPI publish job --- + # --- Manual PyPI Publish Job --- publish-to-pypi: - name: Publish to PyPI - needs: publish-to-testpypi # Depends on TestPyPI publish job succeeding - if: github.event_name == 'workflow_dispatch' # Also only runs on manual trigger (implicitly via needs) + name: Publish Release to PyPI (Manual Trigger) + needs: test # Run tests again before publishing the release + # Runs ONLY on manual workflow_dispatch trigger + if: github.event_name == 'workflow_dispatch' && needs.test.result == 'success' runs-on: ubuntu-latest environment: name: pypi # MUST MATCH the environment name configured in PyPI Trusted Publishers - url: https://pypi.org/p/simulib # Replace YOUR_PACKAGE_NAME + url: https://pypi.org/p/simulib # <-- IMPORTANT: Replace simulib with your package name permissions: id-token: write # Needed for Trusted Publishing on PyPI steps: - name: Checkout code # Checkout code again for this job's environment uses: actions/checkout@v4 + - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.x' + - name: Install uv run: curl -LsSf https://astral.sh/uv/install.sh | sh + - name: Install build dependency using uv run: uv pip install --system --upgrade build - - name: Build package - # Re-build the package in this job's environment + + - name: Build package (using version from pyproject.toml) + # This builds the package using the version defined in your checked-out pyproject.toml + # Assumes this is the intended release version. run: python -m build + - name: Publish package to PyPI using uv and Trusted Publishing - # No --repository-url needed, uv defaults to PyPI - # Authentication happens via OIDC token automatically run: uv publish dist/* - # --- End of PyPI publish job --- From 6b0b9dd1c3521037bd93e45347382bb663b72f18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Vieira?= Date: Fri, 4 Apr 2025 15:27:16 +0000 Subject: [PATCH 25/29] CNF: using existing pypa job for upload --- .github/workflows/main.yml | 125 +++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 68 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c8de7ab..021c6b3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -101,102 +101,91 @@ jobs: # Tell the action to read the comment body from the file we just created path: coverage_comment.md - # --- Automatic TestPyPI Publish Job --- - publish-to-testpypi: - name: Publish Dev Build to TestPyPI - needs: test # Depends on test job succeeding - # Runs ONLY on push events to the main branch (not PRs, not manual triggers) - if: github.ref == 'refs/heads/main' && github.event_name == 'push' && needs.test.result == 'success' +# --- New Job: Publish to TestPyPI (Manual Trigger) --- + publish-testpypi: + name: Publish to TestPyPI + # This job only runs when manually triggered via workflow_dispatch + if: github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest environment: - name: testpypi - url: https://test.pypi.org/p/simulib # <-- IMPORTANT: Replace simulib with your package name + name: testpypi # Environment name configured in GitHub secrets/settings + url: https://test.pypi.org/pypi # URL shown in GH deployments permissions: - id-token: write # Needed for Trusted Publishing + id-token: write # Necessary for trusted publishing + steps: - name: Checkout code uses: actions/checkout@v4 + # Fetch all history so build tools relying on tags/history work with: - fetch-depth: 0 # Fetch all history for versioning if using setuptools_scm later + fetch-depth: 0 - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.x' + python-version: '3.10' # Choose your desired Python version - - name: Install uv - run: curl -LsSf https://astral.sh/uv/install.sh | sh + - name: Install build dependencies + run: python -m pip install build twine - - name: Install build tools and tomlkit - run: uv pip install --system --upgrade build tomlkit + - name: Generate development version suffix + id: version_suffix + # Using timestamp for uniqueness on manual triggers + run: echo "suffix=$(date +'%Y%m%d%H%M%S')" >> $GITHUB_OUTPUT - - name: Set Development Version - id: set_dev_version - # This script reads pyproject.toml, appends .dev to the version, - # and writes it back. Assumes standard `project.version`. - # Adjust ['project']['version'] if your version is elsewhere (e.g., ['tool']['poetry']['version']) + # IMPORTANT: Modify this step based on your project structure + # Option 1: Using sed (example for pyproject.toml with 'version = "..."') + - name: Update version in pyproject.toml for TestPyPI run: | - import tomlkit, os, sys - run_number = os.environ['GITHUB_RUN_NUMBER'] - toml_path = 'pyproject.toml' - try: - with open(toml_path, 'r') as f: data = tomlkit.parse(f.read()) - # *** ADJUST THIS LINE if your version is not at ['project']['version'] *** - base_version = data['project']['version'] - base_version = base_version.split('.dev')[0].split('+')[0] # Clean existing dev/local parts - dev_version = f"{base_version}.dev{run_number}" - print(f"Setting version for TestPyPI: {dev_version}") - # *** ADJUST THIS LINE if your version is not at ['project']['version'] *** - data['project']['version'] = dev_version - with open(toml_path, 'w') as f: f.write(tomlkit.dumps(data)) - # Set output for potential use in other steps (optional) - echo "dev_version=${dev_version}" >> $GITHUB_OUTPUT - except Exception as e: - print(f"Error updating version in {toml_path}: {e}", file=sys.stderr) - sys.exit(1) - env: - GITHUB_RUN_NUMBER: ${{ github.run_number }} - shell: python # Use python directly to run the script block - - - name: Build package with dev version - run: python -m build + # Add .dev suffix to the version line + # This command is basic, adjust the regex if your version format differs + sed -i "s/^\(version\s*=\s*\"\)\(.*\)\"/\1\2.dev${{ steps.version_suffix.outputs.suffix }}\"/" pyproject.toml + echo "Updated pyproject.toml with version suffix:" + grep "^version" pyproject.toml - - name: Publish package to TestPyPI - run: > - uv publish --repository-url https://test.pypi.org/legacy/ dist/* + - name: Build package + run: python -m build - # --- Manual PyPI Publish Job --- - publish-to-pypi: - name: Publish Release to PyPI (Manual Trigger) - needs: test # Run tests again before publishing the release - # Runs ONLY on manual workflow_dispatch trigger - if: github.event_name == 'workflow_dispatch' && needs.test.result == 'success' + - name: Publish package distributions to TestPyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + # No password needed, uses trusted publishing via OIDC + repository-url: https://test.pypi.org/legacy/ # URL for TestPyPI uploads + # skip-existing: true # Optional: prevents failures if version exists + + # --- New Job: Publish to PyPI (Manual Trigger, depends on TestPyPI success) --- + publish-pypi: + name: Publish to PyPI + # This job only runs when manually triggered via workflow_dispatch + if: github.event_name == 'workflow_dispatch' + needs: publish-testpypi # Ensures this runs only after successful TestPyPI publish runs-on: ubuntu-latest environment: - name: pypi # MUST MATCH the environment name configured in PyPI Trusted Publishers - url: https://pypi.org/p/simulib # <-- IMPORTANT: Replace simulib with your package name + name: pypi # Environment name configured in GitHub secrets/settings + url: https://pypi.org/pypi # URL shown in GH deployments permissions: - id-token: write # Needed for Trusted Publishing on PyPI + id-token: write # Necessary for trusted publishing + steps: - name: Checkout code - # Checkout code again for this job's environment uses: actions/checkout@v4 + with: + fetch-depth: 0 # Fetch all history if your build depends on git tags - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.x' - - - name: Install uv - run: curl -LsSf https://astral.sh/uv/install.sh | sh + python-version: '3.10' # Use the same or appropriate Python version - - name: Install build dependency using uv - run: uv pip install --system --upgrade build + - name: Install build dependencies + run: python -m pip install build twine - - name: Build package (using version from pyproject.toml) - # This builds the package using the version defined in your checked-out pyproject.toml - # Assumes this is the intended release version. + - name: Build package run: python -m build + # Builds the package *again* - this time it should use the + # final, clean version committed to your main branch (e.g., "1.2.3") + # Ensure your pyproject.toml or setup.py has the correct final version before triggering. - - name: Publish package to PyPI using uv and Trusted Publishing - run: uv publish dist/* + - name: Publish package distributions to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + # No password or repository_url needed, defaults to PyPI and uses OIDC From 4f2b5f32b16890588893f354b0d1c05d971367ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Vieira?= Date: Fri, 4 Apr 2025 15:35:34 +0000 Subject: [PATCH 26/29] CNF: changed rules for test and main pypi --- .github/workflows/main.yml | 117 ++++++++++++++++++------------------- 1 file changed, 56 insertions(+), 61 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 021c6b3..27f27b9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,14 +1,20 @@ -name: CI - Run Unit Tests in Docker with Coverage +name: CI, TestPyPI Deploy, and Manual PyPI Release on: push: branches: [ main ] pull_request: + # Run on PRs targeting main + types: [opened, synchronize, reopened] # Be explicit about PR event types branches: [ main ] + # Allows manual triggering for publishing steps + workflow_dispatch: jobs: + # --- Test Job (Runs on push/pr/workflow_dispatch) --- test: runs-on: ubuntu-latest + # No 'if' condition needed here, controlled by top-level 'on:' steps: - name: Checkout code uses: actions/checkout@v4 @@ -20,22 +26,15 @@ jobs: uses: docker/build-push-action@v5 with: context: . - file: ./Dockerfile # Assuming Dockerfile is at the root - # Build the 'dev' target stage + file: ./Dockerfile target: dev - # Tag the image locally so subsequent steps can use it tags: my-test-image:latest - # IMPORTANT: Load the image into the local Docker daemon load: true - # Enable layer caching using GitHub Actions cache cache-from: type=gha cache-to: type=gha,mode=max - name: Run tests with dFBA extra run: | - # Runs coverage collection via 'uv run' using --with pytest-cov. - # Uses --parallel-mode for coverage data. - # Generates uniquely named JUnit report. docker run --rm \ -v "$(pwd):/app" \ -w /app \ @@ -44,23 +43,15 @@ jobs: - name: Run tests without dFBA extra run: | - # Runs coverage collection via 'uv run' using --with pytest-cov. - # Uses --parallel-mode for coverage data. - # Generates uniquely named JUnit report. docker run --rm \ -v "$(pwd):/app" \ -w /app \ my-test-image:latest \ uv run --with pytest --with pytest-cov coverage run --parallel-mode -m pytest ./tests/core --junitxml=test-report-core.xml - # --- The step below only runs if BOTH test steps above succeeded --- - - name: Combine and Report Coverage if: success() run: | - # Runs combine, report, and html generation in a single container - # Saves the console summary to /app/coverage_summary.txt within the container - # which maps to coverage_summary.txt on the runner host via the volume mount. docker run --rm \ -v "$(pwd):/app" \ -w /app \ @@ -73,73 +64,75 @@ jobs: echo "Generating HTML coverage report..." && \ uv run --with pytest --with pytest-cov coverage html -d htmlcov \ ' - # Also echo the summary to the main job log for easy viewing there echo "--- Coverage Summary ---" cat coverage_summary.txt echo "------------------------" - name: Format Coverage Comment Body - # Prepare the content for the comment in a file - # Only run on successful PR builds if: success() && github.event_name == 'pull_request' run: | echo '### :test_tube: Coverage Report' > coverage_comment.md echo '' >> coverage_comment.md echo '```text' >> coverage_comment.md cat coverage_summary.txt >> coverage_comment.md - echo '' >> coverage_comment.md # Ensure newline before closing fence + echo '' >> coverage_comment.md echo '```' >> coverage_comment.md - # Optional: Add a hidden HTML comment marker for extra safety/identification - # echo "" >> coverage_comment.md - + - name: Post or Update Coverage Comment - # Use the sticky comment action - # Only run on successful PR builds if: success() && github.event_name == 'pull_request' uses: marocchino/sticky-pull-request-comment@v2 with: - # Tell the action to read the comment body from the file we just created path: coverage_comment.md -# --- New Job: Publish to TestPyPI (Manual Trigger) --- + # --- Job: Publish to TestPyPI (Runs automatically on PRs after tests pass) --- publish-testpypi: - name: Publish to TestPyPI - # This job only runs when manually triggered via workflow_dispatch - if: github.event_name == 'workflow_dispatch' + name: Publish dev build to TestPyPI + # Run after tests succeed, for PRs to main OR manual triggers + needs: test + # No specific 'if' here, runs if 'test' succeeded for a triggering event + # Implicitly runs on pull_request targeting main (from top-level 'on:') + # Implicitly runs on workflow_dispatch (from top-level 'on:') runs-on: ubuntu-latest environment: - name: testpypi # Environment name configured in GitHub secrets/settings - url: https://test.pypi.org/pypi # URL shown in GH deployments + name: testpypi + url: https://test.pypi.org/pypi permissions: - id-token: write # Necessary for trusted publishing + id-token: write # For trusted publishing steps: - name: Checkout code uses: actions/checkout@v4 - # Fetch all history so build tools relying on tags/history work with: - fetch-depth: 0 + fetch-depth: 0 # Needed for accurate versioning if using git tags - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.10' # Choose your desired Python version + python-version: '3.10' - name: Install build dependencies run: python -m pip install build twine - name: Generate development version suffix id: version_suffix - # Using timestamp for uniqueness on manual triggers - run: echo "suffix=$(date +'%Y%m%d%H%M%S')" >> $GITHUB_OUTPUT + # Use PR number/SHA for PRs, timestamp for manual triggers + run: | + if [ "${{ github.event_name }}" == "pull_request" ]; then + # Suffix for PR builds: .dev+ + echo "suffix=dev${{ github.event.number }}+${GITHUB_SHA::7}" >> $GITHUB_OUTPUT + else + # Suffix for other builds (like manual): .dev + echo "suffix=dev$(date +'%Y%m%d%H%M%S')" >> $GITHUB_OUTPUT + fi - # IMPORTANT: Modify this step based on your project structure - # Option 1: Using sed (example for pyproject.toml with 'version = "..."') - name: Update version in pyproject.toml for TestPyPI run: | - # Add .dev suffix to the version line - # This command is basic, adjust the regex if your version format differs - sed -i "s/^\(version\s*=\s*\"\)\(.*\)\"/\1\2.dev${{ steps.version_suffix.outputs.suffix }}\"/" pyproject.toml + # Add the generated .dev suffix to the version line + # This assumes version = "X.Y.Z" format + VERSION_SUFFIX="${{ steps.version_suffix.outputs.suffix }}" + # Use a temporary file for sed compatibility on different OS (though runner is ubuntu) + sed -i.bak "s/^\(version\s*=\s*\"\)\([^\"]*\)\"/\1\2.${VERSION_SUFFIX}\"/" pyproject.toml + rm pyproject.toml.bak # Remove backup file echo "Updated pyproject.toml with version suffix:" grep "^version" pyproject.toml @@ -149,43 +142,45 @@ jobs: - name: Publish package distributions to TestPyPI uses: pypa/gh-action-pypi-publish@release/v1 with: - # No password needed, uses trusted publishing via OIDC - repository-url: https://test.pypi.org/legacy/ # URL for TestPyPI uploads - # skip-existing: true # Optional: prevents failures if version exists + repository-url: https://test.pypi.org/legacy/ + # skip-existing: true # Recommended for dev builds to avoid conflicts - # --- New Job: Publish to PyPI (Manual Trigger, depends on TestPyPI success) --- + # --- Job: Publish to PyPI (Manual Trigger ONLY on main branch) --- publish-pypi: name: Publish to PyPI - # This job only runs when manually triggered via workflow_dispatch - if: github.event_name == 'workflow_dispatch' - needs: publish-testpypi # Ensures this runs only after successful TestPyPI publish + # Run ONLY when manually triggered AND on the main branch + if: github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' + needs: publish-testpypi # Depends on the testpypi build (which runs first on manual trigger) runs-on: ubuntu-latest environment: - name: pypi # Environment name configured in GitHub secrets/settings - url: https://pypi.org/pypi # URL shown in GH deployments + name: pypi + url: https://pypi.org/pypi permissions: - id-token: write # Necessary for trusted publishing + id-token: write # For trusted publishing steps: - name: Checkout code uses: actions/checkout@v4 with: - fetch-depth: 0 # Fetch all history if your build depends on git tags + # Ensure we check out the 'main' branch explicitly for the release build + ref: 'main' + fetch-depth: 0 - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.10' # Use the same or appropriate Python version + python-version: '3.10' - name: Install build dependencies run: python -m pip install build twine - name: Build package - run: python -m build - # Builds the package *again* - this time it should use the - # final, clean version committed to your main branch (e.g., "1.2.3") - # Ensure your pyproject.toml or setup.py has the correct final version before triggering. + run: | + echo "Building package with version:" + grep "^version" pyproject.toml + python -m build + # This builds using the clean version string from the checked-out main branch code - name: Publish package distributions to PyPI uses: pypa/gh-action-pypi-publish@release/v1 - # No password or repository_url needed, defaults to PyPI and uses OIDC + # Defaults to PyPI, uses trusted publishing From f333cfd97864cd1e3d19291663c3a15bdb606cd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Vieira?= Date: Fri, 4 Apr 2025 16:19:23 +0000 Subject: [PATCH 27/29] CNF: add verbose output --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 27f27b9..6ef8cc1 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -143,7 +143,7 @@ jobs: uses: pypa/gh-action-pypi-publish@release/v1 with: repository-url: https://test.pypi.org/legacy/ - # skip-existing: true # Recommended for dev builds to avoid conflicts + verbose: true # --- Job: Publish to PyPI (Manual Trigger ONLY on main branch) --- publish-pypi: From fcc40e3f8796cc7c723121b0eba904a36120ed73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Vieira?= Date: Fri, 4 Apr 2025 16:28:54 +0000 Subject: [PATCH 28/29] CNF: correct dev/main pypi push --- .github/workflows/main.yml | 96 +++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6ef8cc1..5d29240 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,23 +1,25 @@ -name: CI, TestPyPI Deploy, and Manual PyPI Release +name: CI, Test, and Tag-Based Release with Dev TestPyPI on: push: - branches: [ main ] + branches: + - main # Trigger for pushes to main + tags: + - 'v*' # Trigger for pushes of tags like v1.0, v2.3.4 + pull_request: - # Run on PRs targeting main - types: [opened, synchronize, reopened] # Be explicit about PR event types - branches: [ main ] - # Allows manual triggering for publishing steps - workflow_dispatch: + branches: [ main ] # Trigger for PRs targeting main + types: [opened, synchronize, reopened] jobs: - # --- Test Job (Runs on push/pr/workflow_dispatch) --- + # --- Test Job (Remains the same) --- test: runs-on: ubuntu-latest - # No 'if' condition needed here, controlled by top-level 'on:' steps: - name: Checkout code uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -84,26 +86,24 @@ jobs: with: path: coverage_comment.md - # --- Job: Publish to TestPyPI (Runs automatically on PRs after tests pass) --- + # --- Job: Publish DEV version to TestPyPI (Runs ONLY on tag pushes) --- publish-testpypi: - name: Publish dev build to TestPyPI - # Run after tests succeed, for PRs to main OR manual triggers + name: Publish Dev Version to TestPyPI needs: test - # No specific 'if' here, runs if 'test' succeeded for a triggering event - # Implicitly runs on pull_request targeting main (from top-level 'on:') - # Implicitly runs on workflow_dispatch (from top-level 'on:') + # Run ONLY when a tag is pushed, AFTER tests pass + if: success() && startsWith(github.ref, 'refs/tags/') runs-on: ubuntu-latest environment: name: testpypi url: https://test.pypi.org/pypi permissions: - id-token: write # For trusted publishing + id-token: write steps: - name: Checkout code uses: actions/checkout@v4 with: - fetch-depth: 0 # Needed for accurate versioning if using git tags + fetch-depth: 0 - name: Set up Python uses: actions/setup-python@v5 @@ -113,57 +113,56 @@ jobs: - name: Install build dependencies run: python -m pip install build twine + # --- Add step to generate dev suffix --- - name: Generate development version suffix id: version_suffix - # Use PR number/SHA for PRs, timestamp for manual triggers - run: | - if [ "${{ github.event_name }}" == "pull_request" ]; then - # Suffix for PR builds: .dev+ - echo "suffix=dev${{ github.event.number }}+${GITHUB_SHA::7}" >> $GITHUB_OUTPUT - else - # Suffix for other builds (like manual): .dev - echo "suffix=dev$(date +'%Y%m%d%H%M%S')" >> $GITHUB_OUTPUT - fi + # Using timestamp for uniqueness on TestPyPI for potentially repeated tag tests + run: echo "suffix=$(date +'%Y%m%d%H%M%S')" >> $GITHUB_OUTPUT + # --- Add step to update version --- - name: Update version in pyproject.toml for TestPyPI run: | - # Add the generated .dev suffix to the version line - # This assumes version = "X.Y.Z" format + # Add .dev suffix to the version line + # This assumes version = "X.Y.Z" format in pyproject.toml VERSION_SUFFIX="${{ steps.version_suffix.outputs.suffix }}" - # Use a temporary file for sed compatibility on different OS (though runner is ubuntu) - sed -i.bak "s/^\(version\s*=\s*\"\)\([^\"]*\)\"/\1\2.${VERSION_SUFFIX}\"/" pyproject.toml - rm pyproject.toml.bak # Remove backup file - echo "Updated pyproject.toml with version suffix:" + # Use temp file for sed compatibility + sed -i.bak "s/^\(version\s*=\s*\"\)\([^\"]*\)\"/\1\2.dev${VERSION_SUFFIX}\"/" pyproject.toml + rm pyproject.toml.bak # Remove backup + echo "Updated pyproject.toml with dev version suffix for TestPyPI build:" grep "^version" pyproject.toml - - name: Build package - run: python -m build + - name: Build package with dev version + run: | + echo "Building package for tag ${{ github.ref_name }} with dev suffix..." + python -m build - name: Publish package distributions to TestPyPI uses: pypa/gh-action-pypi-publish@release/v1 with: repository-url: https://test.pypi.org/legacy/ - verbose: true + # skip-existing: true # Recommended for dev builds - # --- Job: Publish to PyPI (Manual Trigger ONLY on main branch) --- + # --- Job: Publish CLEAN version to PyPI (Runs ONLY on tag pushes, after TestPyPI) --- publish-pypi: - name: Publish to PyPI - # Run ONLY when manually triggered AND on the main branch - if: github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' - needs: publish-testpypi # Depends on the testpypi build (which runs first on manual trigger) + name: Publish Clean Version to PyPI + needs: publish-testpypi # Depends on the TestPyPI dev publish job + # Run ONLY when a tag is pushed, AFTER TestPyPI publish succeeds + if: success() && startsWith(github.ref, 'refs/tags/') runs-on: ubuntu-latest environment: name: pypi url: https://pypi.org/pypi permissions: - id-token: write # For trusted publishing + id-token: write steps: - - name: Checkout code + # --- Checkout code AGAIN to get the original version --- + - name: Checkout ORIGINAL code for tag uses: actions/checkout@v4 with: - # Ensure we check out the 'main' branch explicitly for the release build - ref: 'main' + # Make sure we're checking out the code corresponding to the tag + # This ensures we get the pyproject.toml WITHOUT the .dev suffix + ref: ${{ github.ref }} fetch-depth: 0 - name: Set up Python @@ -174,13 +173,14 @@ jobs: - name: Install build dependencies run: python -m pip install build twine - - name: Build package + - name: Build package with CLEAN version run: | - echo "Building package with version:" + echo "Building package for tag ${{ github.ref_name }} for PyPI release (using original version)..." grep "^version" pyproject.toml + # Builds the package using the version defined in the tagged commit's source + # because we checked out the original code again. python -m build - # This builds using the clean version string from the checked-out main branch code - name: Publish package distributions to PyPI uses: pypa/gh-action-pypi-publish@release/v1 - # Defaults to PyPI, uses trusted publishing + # Defaults to PyPI, uses trusted publishing via OIDC From 2db6585ed36343539691a5b99ac9fe7e5ffe63bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Vieira?= Date: Fri, 4 Apr 2025 16:32:03 +0000 Subject: [PATCH 29/29] CNF: always run the dev version --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5d29240..1468f2c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -91,7 +91,7 @@ jobs: name: Publish Dev Version to TestPyPI needs: test # Run ONLY when a tag is pushed, AFTER tests pass - if: success() && startsWith(github.ref, 'refs/tags/') + if: success() runs-on: ubuntu-latest environment: name: testpypi