diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 2ee0b386..2f4866b2 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -408,7 +408,7 @@ jobs: - name: Test with pytest working-directory: ${{ env.WORKING_DIR }} if: matrix.project_type == 'application' - run: pytest + run: python -m pytest pixi-linting: strategy: fail-fast: false diff --git a/.github/workflows/testing_fastapi.yml b/.github/workflows/testing_fastapi.yml index 0adce0b7..1c0a78a5 100644 --- a/.github/workflows/testing_fastapi.yml +++ b/.github/workflows/testing_fastapi.yml @@ -196,3 +196,82 @@ jobs: working-directory: ${{ env.WORKING_DIR }} if: matrix.project_type == 'application' run: poetry run pytest + test-setuptools-fastapi-project: + name: test-fastapi-setuptools-setup-fastapi + strategy: + fail-fast: false + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - name: install Rust + uses: dtolnay/rust-toolchain@stable + - name: Cache Rust dependencies + uses: Swatinem/rust-cache@v2.8.1 + - name: Install sqlx-cli + run: cargo install sqlx-cli --no-default-features -F native-tls -F postgres + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "${{ env.MIN_PYTHON_VERSION }}" + - name: Build package + run: cargo build --release -F fastapi + - name: Run creation + run: ./scripts/ci_run_fastapi.sh "fastapi" 4 + shell: bash + - name: Install Dependencies + working-directory: ${{ env.WORKING_DIR }} + run: | + python -m pip install -U pip + python -m pip install -r requirements-dev.txt -r requirements.txt + - name: Pre-commit check + working-directory: ${{ env.WORKING_DIR }} + run: | + pre-commit install + git add . + pre-commit run --all-files + - name: make .env + working-directory: ${{ env.WORKING_DIR }} + run: touch .env + - name: Build and start Docker containers + working-directory: ${{ env.WORKING_DIR }} + run: docker compose up -d + - name: Test with pytest + working-directory: ${{ env.WORKING_DIR }} + run: python -m pytest -n auto + test-setuptools-non-fastapi-project: + name: test-fastapi-setuptools-setup-non-fastapi + strategy: + fail-fast: false + matrix: + project_type: ["application", "lib"] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - name: install Rust + uses: dtolnay/rust-toolchain@stable + - name: Cache Rust dependencies + uses: Swatinem/rust-cache@v2.8.1 + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "${{ env.MIN_PYTHON_VERSION }}" + - name: Build package + run: cargo build --release -F fastapi + - name: Run creation + run: ./scripts/ci_run_fastapi.sh ${{ matrix.project_type }} 4 + shell: bash + - name: Install Dependencies + working-directory: ${{ env.WORKING_DIR }} + run: | + python -m pip install -U pip + python -m pip install -r requirements-dev.txt + - name: Pre-commit check + working-directory: ${{ env.WORKING_DIR }} + run: | + pre-commit install + git add . + pre-commit run --all-files + - name: Test with pytest + working-directory: ${{ env.WORKING_DIR }} + if: matrix.project_type == 'application' + run: python -m pytest diff --git a/src/fastapi/docker_files.rs b/src/fastapi/docker_files.rs index 0a226e79..30e6c0b0 100644 --- a/src/fastapi/docker_files.rs +++ b/src/fastapi/docker_files.rs @@ -532,6 +532,74 @@ EXPOSE 8000 USER appuser +ENTRYPOINT ["./entrypoint.sh"] +"# + ), + ProjectManager::Setuptools => format!( + r#"# syntax=docker/dockerfile:1 + +FROM ubuntu:24.04 AS builder + +WORKDIR /app + +ENV \ + PYTHONUNBUFFERED=true \ + PATH="/root/.local/bin:$PATH" + +RUN : \ + && apt-get update \ + && apt-get install -y --no-install-recommends \ + software-properties-common \ + && add-apt-repository ppa:deadsnakes/ppa \ + && apt-get update \ + && apt-get install -y --no-install-recommends \ + python{python_version} \ + python{python_version}-venv \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +COPY . ./ + +RUN : \ + && python{python_version} -m venv .venv \ + && .venv/bin/python -m pip install -r requirements.txt + + +# Build production stage +FROM ubuntu:24.04 AS prod + +ENV \ + PYTHONUNBUFFERED=true \ + PATH="/app/.venv/bin:$PATH" \ + PORT="8000" + +RUN : \ + && apt-get update \ + && apt-get install -y --no-install-recommends \ + software-properties-common \ + && add-apt-repository ppa:deadsnakes/ppa \ + && apt-get update \ + && apt-get install -y --no-install-recommends \ + python3.13 \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +RUN useradd appuser + +WORKDIR /app + +RUN chown appuser:appuser /app + +COPY --from=builder /app/.venv /app/.venv +COPY --from=builder /app/{source_dir} /app/{source_dir} +COPY ./scripts/entrypoint.sh /app + +RUN chmod +x /app/entrypoint.sh + +EXPOSE 8000 + +USER appuser + ENTRYPOINT ["./entrypoint.sh"] "# ), @@ -692,4 +760,20 @@ mod tests { assert_yaml_snapshot!(content); } + + #[test] + fn test_save_dockerfile_setuptools() { + let mut project_info = project_info_dummy(); + project_info.project_manager = ProjectManager::Setuptools; + let base = project_info.base_dir(); + create_dir_all(&base).unwrap(); + let expected_file = base.join("Dockerfile"); + save_dockerfile(&project_info).unwrap(); + + assert!(expected_file.is_file()); + + let content = std::fs::read_to_string(expected_file).unwrap(); + + assert_yaml_snapshot!(content); + } } diff --git a/src/fastapi/fastapi_installer.rs b/src/fastapi/fastapi_installer.rs index 696f9e4d..76866592 100644 --- a/src/fastapi/fastapi_installer.rs +++ b/src/fastapi/fastapi_installer.rs @@ -131,6 +131,19 @@ fn setuptools_fastapi_depencency_installer(project_info: &ProjectInfo) -> Result bail!("Failed to install FastAPI dependencies: {stderr}"); } + let freeze = std::process::Command::new(".venv/bin/python") + .args(["-m", "pip", "freeze"]) + .current_dir(project_info.base_dir()) + .output()?; + + if !freeze.status.success() { + let stderr = String::from_utf8_lossy(&freeze.stderr); + bail!("Failed to get pip freeze output: {stderr}"); + } + + let requirements_path = project_info.base_dir().join("requirements.txt"); + std::fs::write(requirements_path, freeze.stdout)?; + Ok(()) } diff --git a/src/fastapi/snapshots/python_project__fastapi__docker_files__tests__save_dockerfile_setuptools.snap b/src/fastapi/snapshots/python_project__fastapi__docker_files__tests__save_dockerfile_setuptools.snap new file mode 100644 index 00000000..1a738e16 --- /dev/null +++ b/src/fastapi/snapshots/python_project__fastapi__docker_files__tests__save_dockerfile_setuptools.snap @@ -0,0 +1,5 @@ +--- +source: src/fastapi/docker_files.rs +expression: content +--- +"# syntax=docker/dockerfile:1\n\nFROM ubuntu:24.04 AS builder\n\nWORKDIR /app\n\nENV \\\n PYTHONUNBUFFERED=true \\\n PATH=\"/root/.local/bin:$PATH\"\n\nRUN : \\\n && apt-get update \\\n && apt-get install -y --no-install-recommends \\\n software-properties-common \\\n && add-apt-repository ppa:deadsnakes/ppa \\\n && apt-get update \\\n && apt-get install -y --no-install-recommends \\\n python3.11 \\\n python3.11-venv \\\n && apt-get clean \\\n && rm -rf /var/lib/apt/lists/*\n\nCOPY . ./\n\nRUN : \\\n && python3.11 -m venv .venv \\\n && .venv/bin/python -m pip install -r requirements.txt\n\n\n# Build production stage\nFROM ubuntu:24.04 AS prod\n\nENV \\\n PYTHONUNBUFFERED=true \\\n PATH=\"/app/.venv/bin:$PATH\" \\\n PORT=\"8000\"\n\nRUN : \\\n && apt-get update \\\n && apt-get install -y --no-install-recommends \\\n software-properties-common \\\n && add-apt-repository ppa:deadsnakes/ppa \\\n && apt-get update \\\n && apt-get install -y --no-install-recommends \\\n python3.13 \\\n && apt-get clean \\\n && rm -rf /var/lib/apt/lists/*\n\nRUN useradd appuser\n\nWORKDIR /app\n\nRUN chown appuser:appuser /app\n\nCOPY --from=builder /app/.venv /app/.venv\nCOPY --from=builder /app/my_project /app/my_project\nCOPY ./scripts/entrypoint.sh /app\n\nRUN chmod +x /app/entrypoint.sh\n\nEXPOSE 8000\n\nUSER appuser\n\nENTRYPOINT [\"./entrypoint.sh\"]\n" diff --git a/src/github_actions.rs b/src/github_actions.rs index 9993bebf..0bc305af 100644 --- a/src/github_actions.rs +++ b/src/github_actions.rs @@ -1825,7 +1825,7 @@ jobs: - name: Install Dependencies run: | python -m pip install -U pip - python -m pip -r requirements-dev.txt + python -m pip install -r requirements-dev.txt python -m pip install build setuptools wheel twine - name: Build and publish package run: | @@ -2057,7 +2057,7 @@ jobs: - name: Install Dependencies run: | python -m pip install -U pip - python -m pip -r requirements-dev.txt + python -m pip install -r requirements-dev.txt - name: Publish docs run: mkdocs gh-deploy --force "# diff --git a/src/snapshots/python_project__github_actions__tests__save_docs_publish_file_setuptools.snap b/src/snapshots/python_project__github_actions__tests__save_docs_publish_file_setuptools.snap index 7d6a22f9..df805ae3 100644 --- a/src/snapshots/python_project__github_actions__tests__save_docs_publish_file_setuptools.snap +++ b/src/snapshots/python_project__github_actions__tests__save_docs_publish_file_setuptools.snap @@ -2,4 +2,4 @@ source: src/github_actions.rs expression: content --- -"name: Docs Publish\non:\n release:\n types:\n - published\njobs:\n deploy:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v5\n - name: Set up Python\n uses: actions/setup-python@v6\n with:\n python-version: \"3.12\"\n cache: \"pip\"\n - name: Install Dependencies\n run: |\n python -m pip install -U pip\n python -m pip -r requirements-dev.txt\n - name: Publish docs\n run: mkdocs gh-deploy --force\n" +"name: Docs Publish\non:\n release:\n types:\n - published\njobs:\n deploy:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v5\n - name: Set up Python\n uses: actions/setup-python@v6\n with:\n python-version: \"3.12\"\n cache: \"pip\"\n - name: Install Dependencies\n run: |\n python -m pip install -U pip\n python -m pip install -r requirements-dev.txt\n - name: Publish docs\n run: mkdocs gh-deploy --force\n" diff --git a/src/snapshots/python_project__github_actions__tests__save_pypi_publish_file_setuptools.snap b/src/snapshots/python_project__github_actions__tests__save_pypi_publish_file_setuptools.snap index 80392a0e..6bf5ac41 100644 --- a/src/snapshots/python_project__github_actions__tests__save_pypi_publish_file_setuptools.snap +++ b/src/snapshots/python_project__github_actions__tests__save_pypi_publish_file_setuptools.snap @@ -2,4 +2,4 @@ source: src/github_actions.rs expression: content --- -"name: PyPi Publish\non:\n release:\n types:\n - published\njobs:\n deploy:\n runs-on: ubuntu-latest\n permissions:\n # For PyPI's trusted publishing.\n id-token: write\n steps:\n - uses: actions/checkout@v5\n - name: Set up Python\n uses: actions/setup-python@v6\n with:\n python-version: \"3.12\"\n cache: \"pip\"\n - name: Install Dependencies\n run: |\n python -m pip install -U pip\n python -m pip -r requirements-dev.txt\n python -m pip install build setuptools wheel twine\n - name: Build and publish package\n run: |\n python -m build\n twine upload dist/*\n" +"name: PyPi Publish\non:\n release:\n types:\n - published\njobs:\n deploy:\n runs-on: ubuntu-latest\n permissions:\n # For PyPI's trusted publishing.\n id-token: write\n steps:\n - uses: actions/checkout@v5\n - name: Set up Python\n uses: actions/setup-python@v6\n with:\n python-version: \"3.12\"\n cache: \"pip\"\n - name: Install Dependencies\n run: |\n python -m pip install -U pip\n python -m pip install -r requirements-dev.txt\n python -m pip install build setuptools wheel twine\n - name: Build and publish package\n run: |\n python -m build\n twine upload dist/*\n"