Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,57 +10,65 @@
cancel-in-progress: true
jobs:
build-test-images:
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest ]
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build service TEST image
env:
DOCKER_BUILDKIT: 1
run: |
docker build \
-f service/Dockerfile.test \
-t local/service-test:ci \
service
- name: Save images for downstream jobs
run: |
docker save local/service-test:ci | gzip > service-test.tar.gz
- uses: actions/upload-artifact@v4
with:
name: test-images
path: service-test.tar.gz
service-tests:

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest ]
needs: build-test-images
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: test-images
- name: Load images
run: |
gunzip -c service-test.tar.gz | docker load
- name: Prepare report dir on host (mounted into /reports)
run: mkdir -p service/reports/ci
- name: Run service tests
run: |
docker compose -f docker-compose.test.yml run --rm --entrypoint /bin/sh service_test -lc '
python -m coverage run -m pytest
'
- name: Upload coverage xml
uses: actions/upload-artifact@v4
with:
name: coverage-xml
path: service/reports/ci/coverage.xml
if-no-files-found: error
- name: Cleanup
env:
DOCKER_BUILDKIT: 1
HOST_UID: "1000"
HOST_GID: "1000"
DISPLAY: ":1"
HOST_USERNAME: user
HOST_GROUPNAME: group
if: always()
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ on:
pull_request:
branches: [ "main" ]
schedule:
- cron: '32 14 * * 1'
- cron: '0 0 * * *'

jobs:
analyze:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest ]
os: [ ubuntu-latest, windows-latest ]
python-version: [ "3.9", "3.10", "3.11", "3.12", "3.13" ]
steps:
- uses: actions/checkout@v4
Expand Down
76 changes: 76 additions & 0 deletions .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
name: Pytest
on:
push:
pull_request:
workflow_dispatch:
schedule:
- cron: '0 0 * * *'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
tests:
name: pytest - ${{ matrix.os }} - py${{ matrix.python-version }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest, windows-latest ]
python-version: [ "3.9", "3.10", "3.11", "3.12", "3.13" ]
env:
PYTHONUTF8: "1"
PYTHONPATH: ${{ github.workspace }}/service
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: "pip"

- name: Install deps (Ubuntu)
if: matrix.os == 'ubuntu-latest'
shell: bash
run: |
set -eux
python -m pip install -U pip
pip install -r service/requirements.test.txt
if [ -f service/pyproject.toml ] || [ -f service/setup.cfg ] || [ -f service/setup.py ]; then
pip install -e service
fi
- name: Install deps (Windows)
if: matrix.os == 'windows-latest'
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
python -m pip install -U pip
pip install -r service/requirements.test.txt
$hasPythonProject = (Test-Path -Path 'service/pyproject.toml') -or
(Test-Path -Path 'service/setup.cfg') -or
(Test-Path -Path 'service/setup.py')
if ($hasPythonProject) {
python -m pip install -e service
} else {
Write-Host 'service packaging files not found; skipping'
}
- name: Show versions
shell: bash
run: |
python --version
pip --version
pytest --version
python -c "import sys,platform,os;print(platform.platform());print(sys.version);print('PYTHONPATH=',os.environ.get('PYTHONPATH'))"
- name: Run tests with coverage
shell: bash
run: |
python -m coverage run -m pytest -q
python -m coverage xml -o coverage.xml
- name: Upload coverage.xml
uses: actions/upload-artifact@v4
with:
name: coverage-${{ matrix.os }}-py${{ matrix.python-version }}
path: coverage.xml
if-no-files-found: error
Comment on lines +13 to +75

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI 8 months ago

To fix the problem, add a permissions block to the workflow. The minimal recommended permission is contents: read, which allows jobs read-only access to the repository contents and is sufficient for most test workflows that do not need to write or modify repository resources. This is best added at the root level, immediately after the name and triggers, thereby applying it to all jobs unless overridden at the job level.
Steps:

  • Add the following block after line 1 and before on on line 2 (or, equivalently, after on and before concurrency):
    permissions:
      contents: read
    This will restrict the job’s permissions to the minimum required, satisfying the principle of least privilege and eliminating the CodeQL warning.
Suggested changeset 1
.github/workflows/pytest.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml
--- a/.github/workflows/pytest.yml
+++ b/.github/workflows/pytest.yml
@@ -1,4 +1,6 @@
 name: Pytest
+permissions:
+  contents: read
 on:
   push:
   pull_request:
EOF
@@ -1,4 +1,6 @@
name: Pytest
permissions:
contents: read
on:
push:
pull_request:
Copilot is powered by AI and may make mistakes. Always verify output.

1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

[![CI](https://github.com/europanite/standard_python_environment/actions/workflows/ci.yml/badge.svg)](https://github.com/europanite/standard_python_environment/actions/workflows/ci.yml)
[![Python Lint](https://github.com/europanite/standard_python_environment/actions/workflows/lint.yml/badge.svg)](https://github.com/europanite/standard_python_environment/actions/workflows/lint.yml)
[![Pytest](https://github.com/europanite/standard_python_environment/actions/workflows/pytest.yml/badge.svg)](https://github.com/europanite/standard_python_environment/actions/workflows/pytest.yml)
[![pages-build-deployment](https://github.com/europanite/standard_python_environment/actions/workflows/pages/pages-build-deployment/badge.svg)](https://github.com/europanite/standard_python_environment/actions/workflows/pages/pages-build-deployment)
[![CodeQL Advanced](https://github.com/europanite/standard_python_environment/actions/workflows/codeql.yml/badge.svg)](https://github.com/europanite/standard_python_environment/actions/workflows/codeql.yml)

Expand Down
1 change: 0 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ services:
--port=8888
--no-browser
--NotebookApp.token=''
--notebook-dir=/NotebookApp
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix
- ./service/app:/app
Expand Down
34 changes: 33 additions & 1 deletion service/app/main.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,38 @@
"# write your code.\n",
"print(\"Hello Jupyter\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c9833438-76bb-4358-8771-9ee2f0e96c18",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"id": "5acecb0d-c4a4-4108-946a-9d4bd59cd45c",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"id": "3fd2a5e2-5a62-4159-ab9a-385476aee2c9",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"id": "934e26ad-62df-4b70-b531-992684787463",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
Expand All @@ -36,7 +68,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.11"
"version": "3.12.12"
}
},
"nbformat": 4,
Expand Down
2 changes: 1 addition & 1 deletion service/app/tests/test_notebook.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@


def test_workspace_notebook_runs_and_prints_hello():
nb_path = Path("/app/main.ipynb")
nb_path = Path(__file__).resolve().parents[1] / "main.ipynb"
assert nb_path.exists(), f"Notebook not found: {nb_path}"

nb = nbformat.read(str(nb_path), as_version=4)
Expand Down
12 changes: 12 additions & 0 deletions service/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,15 @@ exclude = [
[tool.ruff.lint]
select = ["E", "F", "I"]
ignore = []

[build-system]
requires = ["setuptools>=68", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "standard_python_environment"
version = "0.0.0"
requires-python = ">=3.9"

[tool.setuptools]
packages = ["app", "data"]
1 change: 1 addition & 0 deletions service/requirements.test.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# write required libraries.
-r requirements.txt
pytest==8.4.2
pytest-cov==5.0.0
ruff==0.13.1