Skip to content

Commit

Permalink
Initialize src
Browse files Browse the repository at this point in the history
  • Loading branch information
Tiant1L authored Sep 10, 2024
0 parents commit 9d94ba0
Show file tree
Hide file tree
Showing 12 changed files with 979 additions and 0 deletions.
18 changes: 18 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.git/
.github/
.dockerignore
Dockerfile

*~
*.DS_Store
*.egg-info/
__pycache__/

.docker

.idea/
.vscode/

examples/

venv/
183 changes: 183 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
# Continuous integration testing for ChRIS Plugin.
# https://github.com/FNNDSC/python-chrisapp-template/wiki/Continuous-Integration
#
# - on push and PR: run pytest
# - on push to main: build and push container images as ":latest"
# - on push to semver tag: build and push container image with tag and
# upload plugin description to https://chrisstore.co

name: build

on:
push:
branches: [ main ]
tags:
- "v?[0-9]+.[0-9]+.[0-9]+*"
pull_request:
branches: [ main ]

jobs:
test:
name: Unit tests
if: false # delete this line to enable automatic testing
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- name: Build
uses: docker/build-push-action@v5
with:
build-args: extras_require=dev
context: .
load: true
push: false
tags: "localhost/local/app:dev"
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Run pytest
run: |
docker run -v "$GITHUB_WORKSPACE:/app:ro" -w /app localhost/local/app:dev \
pytest -o cache_dir=/tmp/pytest
build:
name: Build
if: false # delete this line and uncomment the line below to enable automatic builds
# if: github.event_name == 'push' || github.event_name == 'release'
# needs: [ test ] # uncomment to require passing tests
runs-on: ubuntu-22.04

steps:
- name: Decide image tags
id: info
shell: python
run: |
import os
import itertools
def join_tag(t):
registry, repo, tag = t
return f'{registry}/{repo}:{tag}'.lower()
registries = ['docker.io', 'ghcr.io']
repos = ['${{ github.repository }}']
if '${{ github.ref_type }}' == 'branch':
tags = ['latest']
elif '${{ github.ref_type }}' == 'tag':
tag = '${{ github.ref_name }}'
version = tag[1:] if tag.startswith('v') else tag
tags = ['latest', version]
else:
tags = []
if '${{ github.ref_type }}' == 'tag':
local_tag = join_tag(('ghcr.io', '${{ github.repository }}', version))
else:
local_tag = join_tag(('localhost', '${{ github.repository }}', 'latest'))
product = itertools.product(registries, repos, tags)
tags_csv = ','.join(map(join_tag, product))
outputs = {
'tags_csv' : tags_csv,
'push' : 'true' if tags_csv else 'false',
'local_tag': local_tag
}
with open(os.environ['GITHUB_OUTPUT'], 'a') as out:
for k, v in outputs.items():
out.write(f'{k}={v}\n')
- uses: actions/checkout@v4
# QEMU is used for non-x86_64 builds
- uses: docker/setup-qemu-action@v3
# buildx adds additional features to docker build
- uses: docker/setup-buildx-action@v3
with:
driver-opts: network=host

# Here, we want to do the docker build twice:
# The first build pushes to our local registry for testing.
# The second build pushes to Docker Hub and ghcr.io
- name: Build (local only)
uses: docker/build-push-action@v3
id: docker_build
with:
context: .
file: ./Dockerfile
tags: ${{ steps.info.outputs.local_tag }}
load: true
cache-from: type=gha
# If you have a directory called examples/incoming/ and examples/outgoing/, then
# run your ChRIS plugin with no parameters, and assert that it creates all the files
# which are expected. File contents are not compared.
- name: Run examples
id: run_examples
run: |
if ! [ -d 'examples/incoming/' ] || ! [ -d 'examples/outgoing/' ]; then
echo "No examples."
exit 0
fi
dock_image=${{ steps.info.outputs.local_tag }}
output_dir=$(mktemp -d)
cmd=$(docker image inspect -f '{{ (index .Config.Cmd 0) }}' $dock_image)
docker run --rm -u "$(id -u):$(id -g)" \
-v "$PWD/examples/incoming:/incoming:ro" \
-v "$output_dir:/outgoing:rw" \
$dock_image $cmd /incoming /outgoing
for expected_file in $(find examples/outgoing -type f); do
fname="${expected_file##*/}"
out_path="$output_dir/$fname"
printf "Checking output %s exists..." "$out_path"
if [ -f "$out_path" ]; then
echo "ok"
else
echo "not found"
exit 1
fi
done
- name: Login to DockerHub
if: (github.event_name == 'push' || github.event_name == 'release') && contains(steps.info.outputs.tags_csv, 'docker.io')
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Login to GitHub Container Registry
if: (github.event_name == 'push' || github.event_name == 'release') && contains(steps.info.outputs.tags_csv, 'ghcr.io')
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
if: (github.event_name == 'push' || github.event_name == 'release')
with:
context: .
file: ./Dockerfile
tags: ${{ steps.info.outputs.tags_csv }}
# if non-x86_84 architectures are supported, add them here
platforms: linux/amd64 #,linux/arm64,linux/ppc64le
push: ${{ steps.info.outputs.push }}
cache-to: type=gha,mode=max

- name: Upload ChRIS Plugin
id: upload
if: github.ref_type == 'tag'
uses: FNNDSC/upload-chris-plugin@v1
with:
dock_image: ${{ steps.info.outputs.local_tag }}
username: ${{ secrets.CHRISPROJECT_USERNAME }}
password: ${{ secrets.CHRISPROJECT_PASSWORD }}
chris_url: https://cube.chrisproject.org/api/v1/
compute_names: NERC

- name: Update DockerHub description
if: steps.upload.outcome == 'success'
uses: peter-evans/dockerhub-description@v3
continue-on-error: true # it is not crucial that this works
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
short-description: ${{ steps.upload.outputs.title }}
readme-filepath: ./README.md
140 changes: 140 additions & 0 deletions .github/workflows/src.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
name: Source

on:
push:
branches:
- src
pull_request:
branches:
- src

jobs:
local:
name: Local test
runs-on: ubuntu-20.04
strategy:
matrix:
python-version: [ '3.8.2', '3.9', '3.10', '3.11', '3.12' ]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Configure git
run: |
git config --global user.email "[email protected]"
git config --global user.name "FNNDSC in Github Actions"
- name: Run ./bootstrap.sh
run: |
sed -i -e 's/#READY=yes/READY=yes/' bootstrap.sh
./bootstrap.sh
- name: Generated unit tests
run: |
source venv/bin/activate
pytest
- name: Run program
run: |
source venv/bin/activate
mkdir /tmp/incoming
echo 'on-the-metal test is very testy test test' > /tmp/incoming/ghaction.txt
commandname --word 'test' /tmp/incoming /tmp/outgoing
if ! [ -e '/tmp/outgoing/ghaction.count.txt' ]; then
echo "Contents of /tmp/outgoing: " /tmp/outgoing/*
echo "::error ::File outgoing/ghaction.count.txt was not created."
fi
rm -rvf /tmp/incoming /tmp/outgoing
integration:
name: Integration tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Edit code
run: |
git config --global user.email "[email protected]"
git config --global user.name "FNNDSC in Github Actions"
temp_file=$(mktemp)
sed 's/#READY=yes/READY=yes/' bootstrap.sh \
| sed 's/^PLUGIN_NAME=.*/PLUGIN_NAME=pl-ghactions-testtemplate/' \
| sed 's/^SCRIPT_NAME=.*/SCRIPT_NAME=ghtest_template/' \
| sed 's/^PLUGIN_TITLE=.*/PLUGIN_TITLE="A test in GH Actions"/' \
> $temp_file
mv $temp_file ./bootstrap.sh
chmod +x bootstrap.sh
./bootstrap.sh
if ! [ -f ghtest_template.py ]; then
echo "::error ::File ghtest_template.py was not created."
exit 1
fi
# change the version of this ChRIS plugin
sed -i -e 's/^__version__ = .*/__version__ = "1.2.3"/' ghtest_template.py
- name: Build image
run: docker build -t localhost/fnndsc/pl-ghactions-testtemplate:1.2.3 .
- name: Spin up ChRIS
uses: FNNDSC/miniChRIS-docker@master
with:
plugins: localhost/fnndsc/pl-ghactions-testtemplate:1.2.3
- name: Assert plugin registered
run: |
qs='name_exact=pl-ghactions-testtemplate&version=1.2.3'
res="$(
curl -u 'chris:chris1234' \
-H 'Accept: application/json' \
"http://localhost:8000/api/v1/plugins/search/?$qs"
)"
count="$(jq -r '.count' <<< "$res")"
if [ "$count" != '1' ]; then
echo "::error ::expected count=1"
echo "$res"
exit 1
fi
push:
name: Push to main
if: github.event_name == 'push'
runs-on: ubuntu-latest
needs: [ local, integration ]
steps:
- name: Git checkout
uses: actions/checkout@v4
with:
persist-credentials: false
fetch-depth: 0
- name: Configure git
run: |
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
- name: Merge ref into main
run: |
git switch main
set +e
output="$(git merge --no-ff --no-commit ${{ github.ref }})"
set -e
echo "$output"
# ignore merge conflicts to this file
filtered="$(sed '/CONFLICT (modify\/delete): \.github\/workflows\/src\.yml/d' <<< "$output")"
if ( echo "$filtered" | grep -Fq CONFLICT ); then
echo "::error ::Unacceptable merge conflict. Someone changed main, please merge manually."
exit 1
fi
# Important! Deletes this Github workflow file
if [ -e .github/workflows/src.yml ]; then
git rm --force .github/workflows/src.yml
fi
git commit --no-edit
- name: Push to main
uses: ad-m/github-push-action@552c074ed701137ebd2bf098e70c394ca293e87f
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: main
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
*~
*.DS_Store
*.egg-info/
__pycache__/

.docker

.idea/
.vscode/

venv/
22 changes: 22 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Python version can be changed, e.g.
# FROM python:3.8
# FROM ghcr.io/mamba-org/micromamba:1.5.1-focal-cuda-11.3.1
FROM docker.io/python:3.12.1-slim-bookworm

LABEL org.opencontainers.image.authors="FNNDSC <[email protected]>" \
org.opencontainers.image.title="ChRIS Plugin Title" \
org.opencontainers.image.description="A ChRIS plugin that..."

ARG SRCDIR=/usr/local/src/app
WORKDIR ${SRCDIR}

COPY requirements.txt .
RUN --mount=type=cache,sharing=private,target=/root/.cache/pip pip install -r requirements.txt

COPY . .
ARG extras_require=none
RUN pip install ".[${extras_require}]" \
&& cd / && rm -rf ${SRCDIR}
WORKDIR /

CMD ["commandname"]
Loading

0 comments on commit 9d94ba0

Please sign in to comment.