Skip to content

Commit

Permalink
chore: switch to pyproject
Browse files Browse the repository at this point in the history
  • Loading branch information
yeisonvargasf committed Jan 10, 2025
1 parent 9a6619e commit dbc654c
Show file tree
Hide file tree
Showing 29 changed files with 742 additions and 573 deletions.
69 changes: 48 additions & 21 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,27 +1,54 @@
# Use the official Python 3.12 slim image
FROM python:3.12-slim
FROM python:3.8-alpine

# Create a non-root user and a directory for the application
RUN useradd -m appuser && \
mkdir /app && \
chown appuser:appuser /app
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1

# Set the working directory
WORKDIR /app
RUN apk add --no-cache \
git \
curl \
wget \
zsh \
jq \
sudo \
docker \
docker-compose \
bash \
grep \
sed \
nodejs \
npm \
# Build dependencies for Python packages
gcc \
musl-dev \
python3-dev \
libffi-dev \
openssl-dev \
cargo \
rust \
make && npm install -g pyright

# Set environment variables in a single step
ENV LC_ALL=C.UTF-8 \
LANG=C.UTF-8 \
PYTHONPATH="/app"
RUN pip install --no-cache-dir uv \
&& uv pip install --system hatch hatch-containers

# Install necessary dependencies, clean up after installation to reduce image size
RUN apt-get update && \
apt-get -y install docker.io jq git && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
ARG USERNAME=developer
ARG USER_UID=1000
ARG USER_GID=$USER_UID

# Copy project files into the container (relative to the build context)
COPY . /app/
RUN addgroup -g $USER_GID $USERNAME \
&& adduser -u $USER_UID -G $USERNAME -s /bin/zsh -D $USERNAME \
&& echo "$USERNAME ALL=(root) NOPASSWD:ALL" > /etc/sudoers.d/$USERNAME \
&& chmod 0440 /etc/sudoers.d/$USERNAME \
&& addgroup $USERNAME docker

# Switch to the non-root user for security reasons
USER appuser
RUN sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

RUN sed -i 's|/bin/ash|/bin/zsh|' /etc/passwd

RUN cp -r /root/.oh-my-zsh /home/$USERNAME/ \
&& cp /root/.zshrc /home/$USERNAME/ \
&& chown -R $USERNAME:$USERNAME /home/$USERNAME/.oh-my-zsh \
&& chown $USERNAME:$USERNAME /home/$USERNAME/.zshrc

USER $USERNAME

CMD ["zsh"]
88 changes: 70 additions & 18 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,71 @@
{
"name": "Safety-CLI Dev Container",
"build": {
"dockerfile": "Dockerfile",
"context": "..",
"args": {
"SAFETY_VERSION": "DEV"
}
},
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"ms-python.debugpy"
],
"postCreateCommand": "pip install -r test_requirements.txt && pip install ruff requests pre-commit",
"remoteUser": "root",
"workspaceFolder": "/workspaces/safety",
"forwardPorts": [49152]
}
"name": "Safety CLI Development Environment",

"build": {
"dockerfile": "Dockerfile",
"context": "."
},

"remoteUser": "developer",
"workspaceFolder": "${localWorkspaceFolder}",
"workspaceMount": "source=${localWorkspaceFolder},target=${localWorkspaceFolder},type=bind",


"mounts": [
"source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind",
"source=${localEnv:HOME}${localEnv:USERPROFILE}/.ssh,target=/home/developer/.ssh,type=bind,consistency=cached"
],

"remoteEnv": {
"PYTHONPATH": "${localWorkspaceFolder}",
"TERM": "xterm-256color"
},

"customizations": {
"vscode": {
"settings": {
"terminal.integrated.defaultProfile.linux": "zsh",
"terminal.integrated.profiles.linux": {
"zsh": {
"path": "/bin/zsh"
}
},
"python.defaultInterpreterPath": "${localWorkspaceFolder}/.hatch/bin/python",
"editor.rulers": [80],
"files.exclude": {
"**/__pycache__": true,
"**/.pytest_cache": true
},
"search.exclude": {
"**/.hatch": true,
}
},
"extensions": [
"ms-python.vscode-pylance",
"ms-python.python",
"ms-python.debugpy",
"ms-pyright.pyright",
"charliermarsh.ruff",
"tamasfe.even-better-toml",
"GitHub.copilot",
"streetsidesoftware.code-spell-checker",
"VisualStudioExptTeam.vscodeintellicode",
"VisualStudioExptTeam.intellicode-api-usage-examples",
"mechatroner.rainbow-csv",
"redhat.vscode-yaml",
"eamodio.gitlens",
"github.vscode-github-actions"
]
}
},

"postCreateCommand": "hatch env create default && git config --global core.editor nano",
"postAttachCommand": "sudo chown root:developer /var/run/docker.sock && sudo chmod 660 /var/run/docker.sock && hatch env remove default && hatch env create default",

"containerEnv": {
"SHELL": "/bin/zsh"
},

"waitFor": "postCreateCommand",
"shutdownAction": "stopContainer"
}
18 changes: 0 additions & 18 deletions .editorconfig

This file was deleted.

75 changes: 75 additions & 0 deletions .github/scripts/matrix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# /// script
# requires-python = ">=3.11"
# dependencies = []
# ///
import json
import sys
from pathlib import Path
import tomllib

def read_toml_config(file_path: str) -> dict:
"""Read and parse TOML configuration file."""
with open(file_path, 'rb') as f:
return tomllib.load(f)

def generate_github_matrix(config: dict) -> dict:
"""Generate GitHub Actions matrix configuration from Hatch config."""
test_config = config['tool']['hatch']['envs']['test']
matrix_configs = test_config['matrix']

combinations = []

# This logic is very naive and not future proof, kind of hardcoded.
# TODO: Fix this once we have a clear path about what other configurations
# we want to support.

# First matrix: all Python versions with no target
for python_version in matrix_configs[0]['python']:
combinations.append({
"python-version": python_version,
"target": None,
"os_type": None
})

# Second matrix: specific Python versions with targets
for python_version in matrix_configs[1]['python']:
for target in matrix_configs[1]['targets']:
combinations.append({
"python-version": python_version,
"target": target,
"os_type": None
})

# Third matrix: specific Python versions with os versions
for python_version in matrix_configs[2]['python']:
for target in matrix_configs[2]['targets']:
for os_type in matrix_configs[2]['os_type']:
combinations.append({
"python-version": python_version,
"target": target,
"os_type": os_type
})

return {"include": combinations}

def main():
if len(sys.argv) != 2:
print("Usage: python matrix.py <path_to_pyproject.toml>")
sys.exit(1)

toml_path = Path(sys.argv[1])
if not toml_path.exists():
print(f"Error: File {toml_path} not found")
sys.exit(1)

try:
config = read_toml_config(str(toml_path))
matrix = generate_github_matrix(config)
# Output single-line JSON for GitHub Actions compatibility
print(json.dumps(matrix, separators=(',', ':')))
except Exception as e:
print(f"Error processing TOML file: {e}", file=sys.stderr)
sys.exit(1)

if __name__ == "__main__":
main()
5 changes: 1 addition & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,7 @@ jobs:

- name: Safety Version
run: |
pip install packaging
package_version=$(cat safety/VERSION)
echo $package_version
echo "SAFETY_VERSION=$package_version" >> $GITHUB_ENV
echo "SAFETY_VERSION=$(python -c 'import tomli; print(tomli.load(open("pyproject.toml", "rb"))["project"]["version"])')" >> $GITHUB_ENV
- name: Extract Major and Minor Version
run: |
Expand Down
74 changes: 74 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
name: CI

on:
workflow_call:
push:
branches:
- main
- chore/*
- ci/*
pull_request:
types:
- opened
- synchronize
schedule:
- cron: "0 0 * * 1"

jobs:
matrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}

steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Generate matrix
id: set-matrix
run: |
matrix=$(python .github/scripts/matrix.py pyproject.toml)
echo "Generated matrix:"
echo "$matrix" | jq '.'
echo "matrix=$matrix" >> $GITHUB_OUTPUT
test:
needs: matrix

strategy:
matrix: ${{ fromJson(needs.matrix.outputs.matrix) }}
fail-fast: true

runs-on: ${{ matrix.os_type || 'ubuntu-latest' }}

steps:
- uses: actions/checkout@v4

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

- name: Install Hatch
run: |
python -m pip install --upgrade pip
pip install hatch
- name: Create temporary config
run: |
sed -i 's/type = "container"/type = "virtual"/' pyproject.toml
- name: Run tests
run: |
if [ -z "${{ matrix.target }}" ]; then
# For regular Python version tests
hatch run test.py${{ matrix.python-version }}:test
else
# For tests with specific targets
hatch run test.py${{ matrix.python-version }}-${{ matrix.target }}:test
fi
Loading

0 comments on commit dbc654c

Please sign in to comment.