Compare commits
20 Commits
drew/add-c
...
master
Author | SHA1 | Date |
---|---|---|
Drew Bednar | 4ddd52d37d | 1 year ago |
Drew Bednar | 4fa49fb720 | 1 year ago |
Drew Bednar | c685140890 | 1 year ago |
Drew Bednar | c48d5ba13f | 1 year ago |
Drew Bednar | 66f1df5809 | 1 year ago |
Drew Bednar | e87ba2f3f2 | 1 year ago |
Drew Bednar | 46040764bb | 1 year ago |
Drew Bednar | 8761dbff80 | 1 year ago |
Drew Bednar | cb137d792d | 1 year ago |
Drew Bednar | df128519c7 | 1 year ago |
Drew Bednar | 5544977c96 | 1 year ago |
Drew Bednar | 06dc9fd451 | 1 year ago |
Drew Bednar | 47cc8af0cb | 1 year ago |
Drew Bednar | 7490ed0d3f | 1 year ago |
Drew Bednar | 58763b4eab | 1 year ago |
Drew Bednar | fc6977cf46 | 1 year ago |
Drew Bednar | f72e0082d8 | 1 year ago |
Drew Bednar | 1d544043f8 | 1 year ago |
Drew Bednar | 4859f8a570 | 1 year ago |
Drew Bednar | 6cab703805 | 1 year ago |
@ -1,3 +1,30 @@
|
||||
# cookiecutter-basic
|
||||
|
||||
A basic cookiecutter template for most Androiddrew style repos.
|
||||
A basic [Cookiecutter](https://cookiecutter.readthedocs.io/en/stable) template for most Androiddrew style repos.
|
||||
|
||||
## Usage
|
||||
|
||||
With [Cookiecutter installed](https://cookiecutter.readthedocs.io/en/stable/installation.html), execute the following command and provide your template parameters.
|
||||
|
||||
```
|
||||
cookiecutter https://git.runcible.io/androiddrew/cookiecutter-basic
|
||||
```
|
||||
|
||||
Once templated, you can change into the new project directory and execute the `scripts/bootstrap.sh` script.
|
||||
|
||||
```
|
||||
cd <cookiecutter.project_slug>
|
||||
./scripts/bootstrap.sh
|
||||
```
|
||||
|
||||
This will create a Python virtual environment if one is not already enabled, install [pip-tools](https://github.com/jazzband/pip-tools/), compile the requirements.in and dev-requirements.in files, install the initial dependencies, initialize the project as a git repository, and install the [pre-commit hooks](https://pre-commit.com/).
|
||||
|
||||
## Licenses
|
||||
|
||||
Within a `pyproject.toml` file the license section expects the string identifier as determined by https://spdx.org/licenses/. This project supports a small subset of these licenses.
|
||||
|
||||
Example:
|
||||
```
|
||||
[project]
|
||||
license = {text = "MIT"}
|
||||
```
|
||||
|
@ -1,17 +1,18 @@
|
||||
{
|
||||
"full_name": "Drew Bednar",
|
||||
"email": "drew@androiddrew.com",
|
||||
"email": "drew@runcible.io",
|
||||
"github_username": "androiddrew",
|
||||
"project_name": "python_app",
|
||||
"project_slug": "{{ cookiecutter.project_name.lower().strip().replace(' ', '_').replace('-','_')}}",
|
||||
"initial_dependencies": "",
|
||||
"description": "An templated Python project",
|
||||
"description": "A templated Python project",
|
||||
"image_registry": "registry.runcible.io",
|
||||
"open_source_license": [
|
||||
"MIT license",
|
||||
"BSD license",
|
||||
"ISC license",
|
||||
"Apache Software License 2.0",
|
||||
"GNU General Public License v3",
|
||||
"MIT",
|
||||
"BSD-3-Clause",
|
||||
"ISC",
|
||||
"Apache-2.0",
|
||||
"GPL-3.0-or-later",
|
||||
"Not open source"
|
||||
]
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
./tests
|
||||
./scripts
|
||||
.ruff_cache
|
||||
.coveragerc
|
||||
.dockerignore
|
||||
.git
|
||||
.gitignore
|
||||
.pre-commit-config.yaml
|
||||
dev-requirements.in
|
||||
dev-requirements.txt
|
||||
.profile
|
||||
Dockerfile
|
||||
requirements.in
|
||||
tasks.py
|
@ -1,23 +0,0 @@
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: CI Test Pipeline
|
||||
|
||||
steps:
|
||||
- name: greeting
|
||||
image: alpine
|
||||
commands:
|
||||
- echo "Welcome to drone\n"
|
||||
|
||||
- name: Unit Tests
|
||||
image: python:3.11-bullseye
|
||||
commands:
|
||||
- bash -c './ci_scripts/run_unit_tests.sh'
|
||||
|
||||
trigger:
|
||||
event:
|
||||
- pull_request
|
||||
- push
|
||||
|
||||
# Secrets used to pull private images
|
||||
image_pull_secrets:
|
||||
- dockerconfigjson
|
@ -0,0 +1,44 @@
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: CI Test/Lint Pipeline
|
||||
|
||||
steps:
|
||||
- name: Unit Tests and Linters
|
||||
# Bullseye because drone runner host OS is using older libseccomp2 causing issues
|
||||
# with thread allocation. See: https://github.com/docker-library/python/issues/835
|
||||
image: python:3.11-bullseye
|
||||
commands:
|
||||
- bash -xc './scripts/run_linters.sh'
|
||||
- bash -xc './scripts/run_unit_tests.sh'
|
||||
group: test-lint
|
||||
|
||||
trigger:
|
||||
event:
|
||||
- pull_request
|
||||
- push
|
||||
|
||||
# Secrets used to pull private images
|
||||
image_pull_secrets:
|
||||
- dockerconfigjson
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: Build Production Image
|
||||
steps:
|
||||
- name: Build {{ cookiecutter.project_slug }} Container Image
|
||||
image: plugins/docker
|
||||
settings:
|
||||
username: automate
|
||||
password:
|
||||
from_secret: automate_password
|
||||
dockerfile: Dockerfile
|
||||
registry: {{ cookiecutter.image_registry }}
|
||||
repo: {{ cookiecutter.image_registry }}/{{ cookiecutter.project_slug }}
|
||||
tags:
|
||||
- ${DRONE_COMMIT_SHA}
|
||||
when:
|
||||
branch:
|
||||
- master
|
||||
event:
|
||||
- push
|
@ -0,0 +1,55 @@
|
||||
# syntax = docker/dockerfile:1.4
|
||||
|
||||
# Best practice: Choose a stable base image and tag.
|
||||
FROM python:3.11-slim-bookworm
|
||||
|
||||
# Install security updates, and some useful packages.
|
||||
#
|
||||
# Best practices:
|
||||
# * Make sure apt-get doesn't run in interactive mode.
|
||||
# * Update system packages.
|
||||
# * Pre-install some useful tools.
|
||||
# * Minimize system package installation.
|
||||
RUN export DEBIAN_FRONTEND=noninteractive && \
|
||||
apt-get update && \
|
||||
apt-get -y upgrade && \
|
||||
apt-get install -y --no-install-recommends tini procps net-tools && \
|
||||
apt-get -y clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install dependencies.
|
||||
#
|
||||
# Best practices:
|
||||
# * `COPY` in files only when needed.
|
||||
# * Reduce disk usage from `pip` installs.
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# Create a new user to run as.
|
||||
#
|
||||
# Best practices: Don't run as root.
|
||||
RUN useradd --create-home appuser
|
||||
USER appuser
|
||||
WORKDIR /home/appuser
|
||||
|
||||
# Copy in the code.
|
||||
#
|
||||
# Best practices: Avoid extra chowns.
|
||||
COPY --chown=appuser . .
|
||||
|
||||
# Best practices: Prepare for C crashes.
|
||||
ENV PYTHONFAULTHANDLER=1
|
||||
ENV PYTHONUNBUFFERED=0
|
||||
|
||||
ARG COMMIT_SHA
|
||||
|
||||
LABEL io.runcible.repo-sha="${COMMIT_SHA}"
|
||||
|
||||
# Run the code when the image is run:
|
||||
#
|
||||
# Best practices:
|
||||
# * Add an `init` process.
|
||||
# * Make sure images shut down correctly (via ENTRYPOINT [] syntax).
|
||||
# * '-g' option means killing the container kills all processes, not just the
|
||||
# entrypoint shell.
|
||||
ENTRYPOINT ["tini", "-g", "--", "./entrypoint.sh"]
|
@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Best practice: Bash strict mode.
|
||||
set -euo pipefail
|
||||
|
||||
# Best practice: Make sure the image shuts down correctly by using `exec` in
|
||||
# entry point shell scripts.
|
||||
exec "$@"
|
@ -0,0 +1,28 @@
|
||||
#! /usr/bin/env bash
|
||||
|
||||
# shellcheck source=/dev/null
|
||||
source "$(dirname "$0")/_common.sh"
|
||||
|
||||
if [ "${DRONE}" == "true" ]; then
|
||||
_setup_env
|
||||
pip install -r requirements.txt -r dev-requirements.txt
|
||||
fi
|
||||
|
||||
# Run linting commands and capture their return codes
|
||||
"${VIRTUAL_ENV}/bin/python3" -m isort --check ./speech_collect ./tests ./tasks.py
|
||||
ISORT_EXIT_CODE=$?
|
||||
|
||||
"${VIRTUAL_ENV}/bin/python3" -m black --check ./speech_collect ./tests ./tasks.py
|
||||
BLACK_EXIT_CODE=$?
|
||||
|
||||
"${VIRTUAL_ENV}/bin/python3" -m ruff ./speech_collect ./tests ./tasks.py
|
||||
RUFF_EXIT_CODE=$?
|
||||
|
||||
# Check if any linting command failed
|
||||
if [ $ISORT_EXIT_CODE -ne 0 ] || [ $BLACK_EXIT_CODE -ne 0 ] || [ $RUFF_EXIT_CODE -ne 0 ]; then
|
||||
echo "Some linting checks failed"
|
||||
# Exit with a non-zero status, you can choose which error code to return
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "All linting checks passed"
|
@ -0,0 +1,52 @@
|
||||
import os
|
||||
|
||||
from invoke import task
|
||||
|
||||
IMAGE_RESPOSITORY = os.environ.get("IMAGE_RESPOSITORY", "{{ cookiecutter.image_registry }}/{{ cookiecutter.project_slug }}")
|
||||
|
||||
|
||||
@task
|
||||
def update_deps(c):
|
||||
"""Updates depenencies"""
|
||||
c.run("pip-compile requirements.in", pty=True)
|
||||
c.run("pip-compile dev-requirements.in", pty=True)
|
||||
|
||||
|
||||
@task
|
||||
def sync_deps(c):
|
||||
"""Syncs local dependencies"""
|
||||
c.run("pip-sync requirements.txt dev-requirements.txt")
|
||||
|
||||
|
||||
@task
|
||||
def lint(c):
|
||||
"""Runs all linters against the project."""
|
||||
c.run("./scripts/run_linters.sh", pty=True)
|
||||
|
||||
|
||||
@task
|
||||
def delint(c):
|
||||
"""Applies automated linters to project"""
|
||||
c.run("isort ./{{ cookiecutter.project_slug }} ./tests ./tasks.py", pty=True)
|
||||
c.run("black ./{{ cookiecutter.project_slug }} ./tests ./tasks.py", pty=True)
|
||||
|
||||
|
||||
@task
|
||||
def build(c):
|
||||
"""Builds the project as a Python package."""
|
||||
c.run("python3 -m build")
|
||||
|
||||
|
||||
@task
|
||||
def build_image(c, dev=True, registry_user=None, registry_token=None, push=False, login=False):
|
||||
"""Builds the {{ cookiecutter.project_slug }} container image."""
|
||||
context_dir = c.run("pwd", hide=True).stdout.strip()
|
||||
commit_sha = c.run("git rev-parse --short HEAD", hide=True).stdout.strip()
|
||||
image_name = f"{IMAGE_RESPOSITORY}:{commit_sha}{'-dev' if dev else ''}"
|
||||
c.run(f"docker build --build-arg='COMMIT_SHA={commit_sha}' -t {image_name} {context_dir}")
|
||||
if login:
|
||||
if registry_user is None or registry_token is None:
|
||||
raise ValueError("--registry_user and --registry_token must be provided if using --login parameter")
|
||||
c.run(f"docker login -u {registry_user} -p {registry_token}")
|
||||
if push:
|
||||
c.run(f"docker push {image_name}")
|
Loading…
Reference in New Issue