SciCD
WARNING: this package is in alpha, breaking changes are to be expected
What is it?
SciCD executes scientific workflows as CI/CD pipelines.
To do so, the package transpiles locally executable workflows to CI/CD pipelines
Supported workfow languages:
Supported CI/CD platforms:
Installation
Give the following a shot:
pip install scicd
Why would I want that?
Scalability
- CI/CD schedulers can distribute jobs across computing environments, letting you preprocess on a Slurm cluster, analyze on a cloud Kubernetes cluster, and visualize on your laptop.
Just deploy the open-source
gitlab-runnerin your computing environments of choice. SciCD syncs workflow outputs across environments by using anrclone-compatible remote store.
Reproducibility
- CI/CD execution is containerized and tied to version control. Every exeucution is reproducible.
Portability
- By abstracting at-scale execution to CI/CD, workflow repositories remain lightweight and locally executable.
How does it work?
Let's see a simple example. This is examples/luigi_examples/simple.
To get started, you'll have to register your computer as a Docker executor in your Gitlab instance. For instructions on how to do this, check out the Gitlab documentation.
Now consider the following Luigi workflow in a file called workflow.py.
We've added some in-place configuration, but importantly this is still just Luigi and you can run it in all the ways Luigi is capable of.
However, taking advantage of CI/CD, we've indicated we want to run both tasks on a runner with the tag pc in the python:3.12 container image.
import os
import luigi
# Modified from: https://luigi.readthedocs.io/en/stable/tasks.html
PATH_OUTPUT = os.environ["PATH_OUTPUT"]
class GenerateWords(luigi.Task):
# We added this
scicd = {"image": "python:3.12", "tags": ["pc"]}
words = luigi.ListParameter(default=("apple", "banana", "grapefruit"))
def output(self):
return luigi.LocalTarget(f"{PATH_OUTPUT}/words.txt")
def run(self):
# write a dummy list of words to output file
self.output().makedirs()
with self.output().open("w") as f:
for word in self.words:
f.write(f"{word}\n")
class CountLetters(luigi.Task):
# We added this
scicd = {"image": "python:3.12", "tags": ["pc"]}
def requires(self):
return GenerateWords()
def output(self):
return luigi.LocalTarget(f"{PATH_OUTPUT}/letter_counts.txt")
def run(self):
# read in file as list
with self.input().open("r") as infile:
words = infile.read().splitlines()
# write each word to output file with its corresponding letter count
self.output().makedirs()
with self.output().open("w") as outfile:
for word in words:
outfile.write(
"{word} | {letter_count}\n".format(
word=word, letter_count=len(word)
)
)
You'll also notice we use an environment variable as the base directory for our outputs.
This is a desirable pattern so you can set different outputs paths depending on where the code is executing.
We can set executor-specific environment variables with SciCD by adding a root file called scicd_executors.py.
This file will be automatically detected by scicd, and gives you a chance to inject environment variables relevant for a specific execution environment.
The method receives a TaskConfig object which stores information like the image, tags and resource requests (e.g. cpu).
In Kubernetes or Slurm execution environments, you might want to translate these resources into relevant environment variables.
See examples/luigi_examples/kubernetes for more.
For now, we keep it simple and just inject our PATH_OUTPUT variable.
from typing import Dict
from scicd.config import TaskConfig
from scicd.executor import register_executor
@register_executor(tags=["pc"])
def pc(cfg: TaskConfig) -> Dict[str, str]:
return {"PATH_OUTPUT": "/path/to/local/output"}
We also want to ensure that luigi is installed in the python:3.12 container.
We can do that by configuring SciCD with a root scicd.yaml file.
There's a lot you can do with this file.
Here, we're using the workspace.cicd key to just inject arbtrary Gitlab CI/CD boilerplate, but you can also specify task configuration, remote syncing, and more with this file.
See the examples!
workspace:
cicd:
# This is Gitlab syntax
default:
before_script:
- pip install luigi
Now we're ready to convert this workflow to a .gitlab-ci.yml file!
scicd luigi build --module workflow --task CountLetters --backend gitlab
Out comes the following:
default:
before_script:
- pip install luigi
stages:
- stage_0
- stage_1
GenerateWords:words=["apple","banana","grapefruit"]:
image: python:3.12
tags:
- pc
stage: stage_0
variables:
PATH_OUTPUT: /path/to/local/output
needs: []
script:
- PYTHONPATH=. luigi --module luigi_examples.simple.simple GenerateWords --GenerateWords-words='["apple", "banana", "grapefruit"]' --local-scheduler
CountLetters:
image: python:3.12
tags:
- pc
stage: stage_1
variables:
PATH_OUTPUT: /path/to/local/output
needs:
- GenerateWords:words=["apple","banana","grapefruit"]
script:
- PYTHONPATH=. luigi --module luigi_examples.simple.simple CountLetters --local-scheduler
For more guidance, please look at the examples!
Limitations
While we plan on supporting Github Actions compilation, this has not yet been implemented.
In addition, the transpiler is static and cannot detect dynamic aspects of workflows (like a Luigi task generating additional tasks at runtime). This means dynamic tasks will run in the same job as the discoverable static parent task, and that highly dynamic workflows will be less amenable to the sort of distributed computation unlocked by Ci/CD.
Metadata
Release files for scicd 0.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| scicd-0.0.1.tar.gz | 25.8 kB | Without provenance | Details for scicd-0.0.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| scicd-0.0.1-py3-none-any.whl | Python 3 | none | any | Details for scicd-0.0.1-py3-none-any.whl |
Total release size: 57.9 kB
Release files / scicd-0.0.1.tar.gz
| Download URL | scicd-0.0.1.tar.gz |
|---|---|
| Size | 25.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
326812ec73245e61e254ff08ab9b753e8e5df652584e618a245630afce3b0893
|
|
BLAKE2b-256 checksum How to use checksums |
fc68336630d38ca78442eb48979c76501c075dd86cf36e4513c4fe5f9b820cf9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.11 {"installer":{"name":"uv","version":"0.11.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / scicd-0.0.1-py3-none-any.whl
| Download URL | scicd-0.0.1-py3-none-any.whl |
|---|---|
| Size | 32.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
112df459c8c8b7e917c2e1b897ac8b15df3a97f8c7337b8d711f00416fa945d6
|
|
BLAKE2b-256 checksum How to use checksums |
e87b46e3d529d946c033d406b6b0cc7b9a64742a2aaf3ce69f8b2ee8df928c7d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.11 {"installer":{"name":"uv","version":"0.11.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for scicd 0.0.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.