Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Container Skeleton Workflow Changes #27

Merged
merged 14 commits into from
May 31, 2022
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
31 changes: 31 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# ideas from https://www.docker.com/blog/containerized-python-development-part-1/

# This file is for use as a .vscode devcontainer as well as a runtime
# container. The devcontainer should be rootful and use podman or docker
# with user namespaces.

ARG BASE="mcr.microsoft.com/vscode/devcontainers/python:0-3.10-bullseye"
FROM ${BASE} as base

# use root to pin where the packages will install
USER root
ENV PATH=/root/.local/bin:$PATH

FROM base as developer

WORKDIR /workspace
COPY . .

# install runtime from DIST if there is one
RUN mkdir -p /root/.local && \
if [ -d dist ] ; then \
touch requirements.txt && \
pip install --user -r requirements.txt dist/*.whl ; \
fi

FROM base as runtime

COPY --from=developer /root/.local /root/.local

ENTRYPOINT ["ibek"]
CMD ["--version"]
68 changes: 68 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.231.6/containers/python-3
{
"name": "Python 3",
"build": {
"dockerfile": "Dockerfile",
"target": "developer",
"context": "..",
"args": {}
},
"remoteEnv": {
"DISPLAY": "${localEnv:DISPLAY}"
},
// Set *default* container specific settings.json values on container create.
"settings": {
"python.defaultInterpreterPath": "/usr/local/bin/python",
"python.linting.enabled": true,
"python.linting.pylintEnabled": true,
"python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8",
"python.formatting.blackPath": "/usr/local/py-utils/bin/black",
"python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf",
"python.linting.banditPath": "/usr/local/py-utils/bin/bandit",
"python.linting.flake8Path": "/usr/local/py-utils/bin/flake8",
"python.linting.mypyPath": "/usr/local/py-utils/bin/mypy",
"python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle",
"python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle",
"python.linting.pylintPath": "/usr/local/py-utils/bin/pylint"
},
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"streetsidesoftware.code-spell-checker",
"ryanluker.vscode-coverage-gutters",
"mhutchie.git-graph",
"eamodio.gitlens",
"gruntfuggly.todo-tree",
"redhat.vscode-yaml",
"nsd.vscode-epics",
"alefragnani.bookmarks"
],
"features": {
//"docker-from-docker": "20.10",
"git": "os-provided"
},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
// "remoteUser": "vscode",
// Make sure the files we are mapping into the container exist on the host
"initializeCommand": "bash -c 'for i in $HOME/.inputrc $HOME/.bashrc_dev; do [ -f $i ] || touch $i; done'",
"runArgs": [
"--privileged",
"--net=host",
"-v=${localEnv:HOME}/.ssh:/root/.ssh",
"-v=${localEnv:HOME}/.bashrc_dev:/root/.bashrc",
"-v=${localEnv:HOME}/.inputrc:/root/.inputrc"
],
"mounts": [
// map in home directory - not strictly necessary but may be useful
"source=${localEnv:HOME},target=${localEnv:HOME},type=bind,consistency=cached"
],
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind",
"workspaceFolder": "/workspace",
// After the container is created, install the python project in editable form
// This installs into the system python of the container
"postCreateCommand": "pip install $([ -f requirements_dev.txt ] && echo -r requirements_dev.txt ) -e .[dev]"
}
18 changes: 18 additions & 0 deletions .devcontainer/local_build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# locally build a runtime container for testing

# first make sure a wheel is built
(
cd ..
pip install build
rm -r dist
python -m build --wheel
)

# make the container name the same as the root folder name of this clone
container_name=$(cd ..; basename $(realpath .))
echo building $container_name ...

# run the build with required build-args for a runtime build
ln -s ../dist .
podman build --build-arg BASE=python:3.10-slim --build-arg ENTRYPOINT=$container_name -t $container_name .. --file ./Dockerfile
unlink dist
16 changes: 9 additions & 7 deletions .github/pages/index.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<title>Redirecting to master branch</title>
<meta charset="utf-8">
<meta http-equiv="refresh" content="0; url=./master/index.html">
<link rel="canonical" href="master/index.html">
</head>
</html>

<head>
<title>Redirecting to master branch</title>
<meta charset="utf-8">
<meta http-equiv="refresh" content="0; url=./master/index.html">
<link rel="canonical" href="master/index.html">
</head>

</html>
168 changes: 135 additions & 33 deletions .github/workflows/code.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,77 +13,120 @@ on:
pull_request:
schedule:
# Run every Monday at 8am to check latest versions of dependencies
- cron: '0 8 * * MON'
- cron: "0 8 * * MON"

jobs:
lint:
runs-on: "ubuntu-latest"
steps:
- name: Run black, flake8, mypy
uses: dls-controls/pipenv-run-action@v1
with:
pipenv-run: lint
- name: Checkout
uses: actions/checkout@v2

- name: Lint
run: |
pip install --user .[dev]
tox -e pre-commit,mypy

wheel:
runs-on: "ubuntu-latest"
strategy:
fail-fast: false
matrix:
os: ["ubuntu-latest"]
python: ["3.8"]

runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0

- name: Create Sdist and Wheel
# Set SOURCE_DATE_EPOCH from git commit for reproducible build
# https://reproducible-builds.org/
# Set group writable and umask to do the same to match inside DLS
run: |
chmod -R g+w .
umask 0002
SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct) pipx run build --sdist --wheel

- name: Test cli works from the installed wheel
# Can remove the repository reference after https://github.com/pypa/pipx/pull/733
run: pipx run --spec dist/*.whl ${GITHUB_REPOSITORY##*/} --version

- name: Upload Wheel and Sdist as artifacts
uses: actions/upload-artifact@v2
with:
name: dist
path: dist/*
path: dist

- name: Install minimum python version
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python }}

- name: Install wheel in a venv and check cli works
# ${GITHUB_REPOSITORY##*/} is the repo name without org
# Replace this with the cli command if different to the repo name
run: pipx run --python $(which python${{ matrix.python }}) --spec dist/*.whl ${GITHUB_REPOSITORY##*/} --version

test:
strategy:
fail-fast: false
matrix:
os: ["ubuntu-latest"] # can add windows-latest, macos-latest
python: ["3.7", "3.8", "3.9"]
pipenv: ["skip-lock"]
os: ["ubuntu-latest"] # can add windows-latest, macos-latest
python: ["3.8", "3.9", "3.10"]
lock: [false]

include:
# Add an extra Python3.7 runner to use the lockfile
# Add an extra Python3.10 runner to use the lockfile
- os: "ubuntu-latest"
python: "3.7"
pipenv: "deploy"
python: "3.10"
lock: true

runs-on: ${{ matrix.os }}
env:
# https://github.com/pytest-dev/pytest/issues/2042
PY_IGNORE_IMPORTMISMATCH: "1"
# enable QT tests with no X Display
QT_QPA_PLATFORM: "offscreen"

steps:
- name: Setup repo and test
uses: dls-controls/pipenv-run-action@v1
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0

- name: Setup python ${{ matrix.python }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python }}
pipenv-install: --dev --${{ matrix.pipenv }}
allow-editable-installs: ${{ matrix.pipenv == 'deploy' }}
pipenv-run: tests

- name: Install with locked dependencies
if: matrix.lock
run: |
touch requirements.txt requirements_dev.txt
pip install -r requirements.txt -e .
pip freeze --exclude-editable > requirements.txt
pip install -r requirements_dev.txt -e .[dev]
pip freeze --exclude-editable > requirements_dev.txt

- name: Install with latest dependencies
if: ${{ ! matrix.lock }}
run: pip install -e .[dev]

- name: Run tests
run: pytest tests

- name: Create requirements_dev.txt
run: |
pip freeze --exclude-editable > requirements_dev.txt

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v2
with:
name: ${{ matrix.python }}/${{ matrix.os }}/${{ matrix.pipenv }}
name: ${{ matrix.python }}/${{ matrix.os }}/${{ matrix.lock }}
files: cov.xml

- name: Upload lockfiles
if: matrix.lock
uses: actions/upload-artifact@v2
with:
name: lockfiles
path: |
requirements.txt
requirements_dev.txt

release:
needs: [lint, wheel, test]
runs-on: ubuntu-latest
Expand All @@ -92,15 +135,16 @@ jobs:
steps:
- uses: actions/download-artifact@v2
with:
name: dist
path: dist
path: artifacts

- name: Github Release
# We pin to the SHA, not the tag, for security reasons.
# https://docs.github.com/en/actions/learn-github-actions/security-hardening-for-github-actions#using-third-party-actions
uses: softprops/action-gh-release@1e07f4398721186383de40550babbdf2b84acfc5 # v0.1.14
uses: softprops/action-gh-release@1e07f4398721186383de40550babbdf2b84acfc5 # v0.1.14
with:
files: dist/*
files: |
artifacts/dist/*
artifacts/lockfiles/*
generate_release_notes: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand All @@ -109,4 +153,62 @@ jobs:
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.pypi_token }}
run: pipx run twine upload dist/*
run: pipx run twine upload artifacts/dist/*

make-container:
needs: [lint, wheel, test]
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- name: Checkout
uses: actions/checkout@v2

- uses: actions/download-artifact@v2
with:
name: dist
path: dist

- name: Cache Docker layers
uses: actions/cache@v2
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-

- name: Log in to GitHub Docker Registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Docker meta
id: meta
uses: docker/metadata-action@v4
with:
images: ghcr.io/${{ github.repository }}
tags: |
type=ref,event=branch
type=ref,event=tag
type=raw,value=latest

- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1

- name: Build runtime image
uses: docker/build-push-action@v2
with:
file: .devcontainer/Dockerfile
context: .
push: ${{ github.event_name != 'pull_request' }}
build-args: BASE=python:3.10-slim
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache
Loading