easylink 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. easylink-0.1.0/.bandit +2 -0
  2. easylink-0.1.0/.flake8 +39 -0
  3. easylink-0.1.0/.github/CODEOWNERS +2 -0
  4. easylink-0.1.0/.github/pull_request_template.md +21 -0
  5. easylink-0.1.0/.github/workflows/build.yml +37 -0
  6. easylink-0.1.0/.github/workflows/deploy.yml +50 -0
  7. easylink-0.1.0/.gitignore +151 -0
  8. easylink-0.1.0/CHANGELOG.rst +3 -0
  9. easylink-0.1.0/Jenkinsfile +259 -0
  10. easylink-0.1.0/Makefile +101 -0
  11. easylink-0.1.0/PKG-INFO +93 -0
  12. easylink-0.1.0/README.rst +63 -0
  13. easylink-0.1.0/pyproject.toml +11 -0
  14. easylink-0.1.0/pytype.cfg +14 -0
  15. easylink-0.1.0/setup.cfg +4 -0
  16. easylink-0.1.0/setup.py +71 -0
  17. easylink-0.1.0/src/easylink/__about__.py +19 -0
  18. easylink-0.1.0/src/easylink/__init__.py +10 -0
  19. easylink-0.1.0/src/easylink/_version.py +1 -0
  20. easylink-0.1.0/src/easylink/cli.py +131 -0
  21. easylink-0.1.0/src/easylink/configuration.py +232 -0
  22. easylink-0.1.0/src/easylink/graph_components.py +158 -0
  23. easylink-0.1.0/src/easylink/images/spark_cluster/Dockerfile +16 -0
  24. easylink-0.1.0/src/easylink/images/spark_cluster/README.md +15 -0
  25. easylink-0.1.0/src/easylink/implementation.py +138 -0
  26. easylink-0.1.0/src/easylink/implementation_metadata.yaml +142 -0
  27. easylink-0.1.0/src/easylink/pipeline.py +188 -0
  28. easylink-0.1.0/src/easylink/pipeline_graph.py +337 -0
  29. easylink-0.1.0/src/easylink/pipeline_schema.py +81 -0
  30. easylink-0.1.0/src/easylink/pipeline_schema_constants/__init__.py +9 -0
  31. easylink-0.1.0/src/easylink/pipeline_schema_constants/development.py +191 -0
  32. easylink-0.1.0/src/easylink/pipeline_schema_constants/integration_test.py +39 -0
  33. easylink-0.1.0/src/easylink/rule.py +185 -0
  34. easylink-0.1.0/src/easylink/runner.py +154 -0
  35. easylink-0.1.0/src/easylink/step.py +732 -0
  36. easylink-0.1.0/src/easylink/steps/dev/README.md +89 -0
  37. easylink-0.1.0/src/easylink/steps/dev/build-containers-local.sh +12 -0
  38. easylink-0.1.0/src/easylink/steps/dev/build-containers-remote.sh +12 -0
  39. easylink-0.1.0/src/easylink/steps/dev/input_data/create_input_files.ipynb +105 -0
  40. easylink-0.1.0/src/easylink/steps/dev/input_data/input_file_1.csv +10001 -0
  41. easylink-0.1.0/src/easylink/steps/dev/input_data/input_file_1.parquet +0 -0
  42. easylink-0.1.0/src/easylink/steps/dev/input_data/input_file_2.csv +10001 -0
  43. easylink-0.1.0/src/easylink/steps/dev/input_data/input_file_2.parquet +0 -0
  44. easylink-0.1.0/src/easylink/steps/dev/python_pandas/README.md +25 -0
  45. easylink-0.1.0/src/easylink/steps/dev/python_pandas/dummy_step.py +125 -0
  46. easylink-0.1.0/src/easylink/steps/dev/python_pandas/python_pandas.def +33 -0
  47. easylink-0.1.0/src/easylink/steps/dev/python_pyspark/README.md +32 -0
  48. easylink-0.1.0/src/easylink/steps/dev/python_pyspark/dummy_step.py +140 -0
  49. easylink-0.1.0/src/easylink/steps/dev/python_pyspark/python_pyspark.def +36 -0
  50. easylink-0.1.0/src/easylink/steps/dev/r/README.md +27 -0
  51. easylink-0.1.0/src/easylink/steps/dev/r/dummy_step.R +129 -0
  52. easylink-0.1.0/src/easylink/steps/dev/r/r-image.def +29 -0
  53. easylink-0.1.0/src/easylink/steps/dev/test.py +206 -0
  54. easylink-0.1.0/src/easylink/utilities/__init__.py +8 -0
  55. easylink-0.1.0/src/easylink/utilities/data_utils.py +60 -0
  56. easylink-0.1.0/src/easylink/utilities/general_utils.py +111 -0
  57. easylink-0.1.0/src/easylink/utilities/paths.py +10 -0
  58. easylink-0.1.0/src/easylink/utilities/spark.smk +202 -0
  59. easylink-0.1.0/src/easylink/utilities/validation_utils.py +23 -0
  60. easylink-0.1.0/src/easylink.egg-info/PKG-INFO +93 -0
  61. easylink-0.1.0/src/easylink.egg-info/SOURCES.txt +101 -0
  62. easylink-0.1.0/src/easylink.egg-info/dependency_links.txt +1 -0
  63. easylink-0.1.0/src/easylink.egg-info/entry_points.txt +2 -0
  64. easylink-0.1.0/src/easylink.egg-info/not-zip-safe +1 -0
  65. easylink-0.1.0/src/easylink.egg-info/requires.txt +24 -0
  66. easylink-0.1.0/src/easylink.egg-info/top_level.txt +1 -0
  67. easylink-0.1.0/tests/__init__.py +0 -0
  68. easylink-0.1.0/tests/conftest.py +39 -0
  69. easylink-0.1.0/tests/e2e/test_easylink_run.py +122 -0
  70. easylink-0.1.0/tests/e2e/test_step_types.py +83 -0
  71. easylink-0.1.0/tests/integration/test_snakemake.py +40 -0
  72. easylink-0.1.0/tests/integration/test_snakemake_slurm.py +69 -0
  73. easylink-0.1.0/tests/integration/test_snakemake_spark.py +83 -0
  74. easylink-0.1.0/tests/specifications/common/environment_local.yaml +2 -0
  75. easylink-0.1.0/tests/specifications/common/input_data.yaml +3 -0
  76. easylink-0.1.0/tests/specifications/common/pipeline.yaml +13 -0
  77. easylink-0.1.0/tests/specifications/e2e/environment_slurm.yaml +16 -0
  78. easylink-0.1.0/tests/specifications/e2e/pipeline.yaml +19 -0
  79. easylink-0.1.0/tests/specifications/e2e/pipeline_expanded.yaml +29 -0
  80. easylink-0.1.0/tests/specifications/integration/environment_spark_slurm.yaml +16 -0
  81. easylink-0.1.0/tests/specifications/integration/pipeline.yaml +4 -0
  82. easylink-0.1.0/tests/specifications/integration/pipeline_spark.yaml +4 -0
  83. easylink-0.1.0/tests/unit/__init__.py +0 -0
  84. easylink-0.1.0/tests/unit/conftest.py +627 -0
  85. easylink-0.1.0/tests/unit/rule_strings/implemented_rule_local.txt +20 -0
  86. easylink-0.1.0/tests/unit/rule_strings/implemented_rule_slurm.txt +26 -0
  87. easylink-0.1.0/tests/unit/rule_strings/pipeline_local.txt +133 -0
  88. easylink-0.1.0/tests/unit/rule_strings/pipeline_slurm.txt +157 -0
  89. easylink-0.1.0/tests/unit/rule_strings/target_rule.txt +12 -0
  90. easylink-0.1.0/tests/unit/rule_strings/validation_rule.txt +10 -0
  91. easylink-0.1.0/tests/unit/test_cli.py +8 -0
  92. easylink-0.1.0/tests/unit/test_config.py +207 -0
  93. easylink-0.1.0/tests/unit/test_data_utils.py +55 -0
  94. easylink-0.1.0/tests/unit/test_general_utils.py +11 -0
  95. easylink-0.1.0/tests/unit/test_graph_components.py +138 -0
  96. easylink-0.1.0/tests/unit/test_implementation.py +25 -0
  97. easylink-0.1.0/tests/unit/test_pipeline.py +47 -0
  98. easylink-0.1.0/tests/unit/test_pipeline_graph.py +631 -0
  99. easylink-0.1.0/tests/unit/test_pipeline_schema.py +156 -0
  100. easylink-0.1.0/tests/unit/test_rule.py +115 -0
  101. easylink-0.1.0/tests/unit/test_runner.py +49 -0
  102. easylink-0.1.0/tests/unit/test_step.py +615 -0
  103. easylink-0.1.0/tests/unit/test_validations.py +438 -0
easylink-0.1.0/.bandit ADDED
@@ -0,0 +1,2 @@
1
+ [bandit]
2
+ exclude: tests
easylink-0.1.0/.flake8 ADDED
@@ -0,0 +1,39 @@
1
+ [flake8]
2
+ # Use the following flake8 plugins:
3
+ # ANN : flake8-annotations
4
+ # B,B9 : flake8-bugbear
5
+ # BLK : flake8-black
6
+ # C : mccabe code complexity
7
+ # D : flake8-docstrings
8
+ # DAR : darglint. Not currently in use because it was too slow.
9
+ # F : pyflakes
10
+ # I : flake8-isort
11
+ # S : flake8-bandit
12
+ # W,E : pycodestyle (pep8) warnings and errors
13
+ select = ANN,B,B9,BLK,C,D,E,F,I,S,W
14
+
15
+ # Ignore these flake8 errors across the board.
16
+ extend-ignore =
17
+ ANN101, # Missing type annotation for self
18
+ ANN102, # Missing type annotation for cls
19
+ ANN204, # Missing type annotation for special method
20
+ D100, # Missing docstring in public module
21
+ D104, # Missing docstring in public package
22
+ E203, # Colons should not have whitespace before them (needed for black)
23
+ W503, # Line break before binary operator (needed for black)
24
+
25
+ # Only use strict docstring linting in the api/ or cli/ directory. Unfortunately it's not
26
+ # possible to enable only those directories, so instead we disable strict docstring linting
27
+ # everywhere else.
28
+ # Also allow unused imports in __init__ files.
29
+ per-file-ignores =
30
+ tests/**:D105,D106,D107,D205,D207,D208,D212,D214,D215,D301,D4,S101
31
+ src/vivarium_gbd_access/lib/**:D105,D106,D107,D205,D207,D208,D212,D214,D215,D301,D4
32
+ **/__init__.py:F401
33
+
34
+ # Function complexity and line length
35
+ max-complexity = 10
36
+ max-line-length = 95
37
+
38
+ # Docstrings
39
+ docstring-convention = google
@@ -0,0 +1,2 @@
1
+ # default owners
2
+ * @aflaxman @albrja @hussain-jafari @patricktnast @rmudambi @stevebachmeier @zmbc
@@ -0,0 +1,21 @@
1
+ ## Title: Summary, imperative, start upper case, don't end with a period
2
+ <!-- Ideally, <=50 chars. 50 chars is here..: -->
3
+
4
+ ### Description
5
+ <!-- For use in commit message, wrap at 72 chars. 72 chars is here: -->
6
+ - *Category*: <!-- one of bugfix, implementation, refactor, revert,
7
+ test, release, other/misc -->
8
+ - *JIRA issue*: https://jira.ihme.washington.edu/browse/MIC-XYZ
9
+ - *Research reference*: <!--Link to research documentation for code -->
10
+
11
+ ### Changes and notes
12
+ <!--
13
+ Change description – why, what, anything unexplained by the above.
14
+ Include guidance to reviewers if changes are complex.
15
+ -->
16
+
17
+ ### Verification and Testing
18
+ <!--
19
+ Details on how code was verified. Consider: plots, images, (small) csv files.
20
+ -->
21
+
@@ -0,0 +1,37 @@
1
+ # -----------------------------------------------------------------------------
2
+ # - invoked on push, pull_request, or manual trigger
3
+ # - test under at least 3 versions of python
4
+ # -----------------------------------------------------------------------------
5
+ name: build
6
+ on: [push, pull_request, workflow_dispatch]
7
+
8
+ jobs:
9
+ build:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ matrix:
13
+ python-version: ["3.11", "3.12"]
14
+ steps:
15
+ - uses: actions/checkout@v3
16
+ - name: Set up Python ${{ matrix.python-version }}
17
+ uses: actions/setup-python@v4
18
+ with:
19
+ python-version: ${{ matrix.python-version }}
20
+ - name: Print environment values
21
+ run: |
22
+ python --version
23
+ cat $GITHUB_ENV
24
+ - name: Update pip
25
+ run: |
26
+ python -m pip install --upgrade pip
27
+ - name: Lint
28
+ run: |
29
+ pip install black==22.3.0 isort
30
+ black . --check --diff
31
+ isort . --check --verbose --only-modified --diff
32
+ - name: Install dependencies
33
+ run: |
34
+ pip install .[dev]
35
+ - name: Test
36
+ run: |
37
+ pytest ./tests
@@ -0,0 +1,50 @@
1
+ name: deploy
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ deploy:
9
+ runs-on: ubuntu-latest
10
+ permissions:
11
+ id-token: write
12
+ steps:
13
+ - uses: actions/checkout@v3
14
+ - name: Set up Python
15
+ uses: actions/setup-python@v4
16
+ with:
17
+ python-version: '3.11'
18
+ - name: Install dependencies
19
+ run: |
20
+ python --version
21
+ python -m pip install --upgrade pip
22
+ pip install setuptools wheel build
23
+ - name: Test
24
+ run: |
25
+ pip install .[test]
26
+ pytest ./tests
27
+ - name: Build
28
+ run: python -m build
29
+ - name: Publish
30
+ uses: pypa/gh-action-pypi-publish@release/v1
31
+ - name: Send mail
32
+ # Notify when cron job fails
33
+ if: failure()
34
+ uses: dawidd6/action-send-mail@v2
35
+ with:
36
+ # mail server settings
37
+ server_address: smtp.gmail.com
38
+ server_port: 465
39
+ # user credentials
40
+ username: ${{ secrets.NOTIFY_EMAIL }}
41
+ password: ${{ secrets.NOTIFY_PASSWORD }}
42
+ # email subject
43
+ subject: ${{ github.job }} job of ${{ github.repository }} has ${{ job.status }}
44
+ # email body as text
45
+ body: ${{ github.job }} job in worflow ${{ github.workflow }} of ${{ github.repository }} has ${{ job.status }}
46
+ # comma-separated string, send email to
47
+ to: uw_ihme_simulationscience@uw.edu
48
+ # from email name
49
+ from: Vivarium Notifications
50
+
@@ -0,0 +1,151 @@
1
+ **/*.tar
2
+ **/*.tar.gz
3
+ **/*.sif
4
+
5
+ # Byte-compiled / optimized / DLL files
6
+ __pycache__/
7
+ *.py[cod]
8
+ *$py.class
9
+
10
+ # C extensions
11
+ *.so
12
+
13
+ # Distribution / packaging
14
+ .Python
15
+ build/
16
+ develop-eggs/
17
+ dist/
18
+ downloads/
19
+ eggs/
20
+ .eggs/
21
+ lib/
22
+ lib64/
23
+ parts/
24
+ sdist/
25
+ var/
26
+ wheels/
27
+ pip-wheel-metadata/
28
+ share/python-wheels/
29
+ *.egg-info/
30
+ .installed.cfg
31
+ *.egg
32
+ *.pyc
33
+ MANIFEST
34
+
35
+ # PyInstaller
36
+ # Usually these files are written by a python script from a template
37
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
38
+ *.manifest
39
+ *.spec
40
+
41
+ # Installer logs
42
+ pip-log.txt
43
+ pip-delete-this-directory.txt
44
+
45
+ # Unit test / coverage reports
46
+ htmlcov/
47
+ .tox/
48
+ .nox/
49
+ .coverage
50
+ .coverage.*
51
+ .cache
52
+ nosetests.xml
53
+ coverage.xml
54
+ *.cover
55
+ *.py,cover
56
+ .hypothesis/
57
+ .pytest_cache/
58
+
59
+ # Translations
60
+ *.mo
61
+ *.pot
62
+
63
+ # Django stuff:
64
+ *.log
65
+ local_settings.py
66
+ db.sqlite3
67
+ db.sqlite3-journal
68
+
69
+ # Flask stuff:
70
+ instance/
71
+ .webassets-cache
72
+
73
+ # Scrapy stuff:
74
+ .scrapy
75
+
76
+ # Sphinx documentation
77
+ docs/_build/
78
+
79
+ # PyBuilder
80
+ target/
81
+
82
+ # Jupyter Notebook
83
+ .ipynb_checkpoints
84
+
85
+ # IPython
86
+ profile_default/
87
+ ipython_config.py
88
+
89
+ # pyenv
90
+ .python-version
91
+
92
+ # pipenv
93
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
94
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
95
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
96
+ # install all needed dependencies.
97
+ #Pipfile.lock
98
+
99
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
100
+ __pypackages__/
101
+
102
+ # Celery stuff
103
+ celerybeat-schedule
104
+ celerybeat.pid
105
+
106
+ # SageMath parsed files
107
+ *.sage.py
108
+
109
+ # Environments
110
+ .env
111
+ .venv
112
+ env/
113
+ venv/
114
+ ENV/
115
+ env.bak/
116
+ venv.bak/
117
+
118
+ # Spyder project settings
119
+ .spyderproject
120
+ .spyproject
121
+
122
+ # Rope project settings
123
+ .ropeproject
124
+
125
+ # mkdocs documentation
126
+ /site
127
+
128
+ # mypy
129
+ .mypy_cache/
130
+ .dmypy.json
131
+ dmypy.json
132
+
133
+ # Pycharm project settings
134
+ .idea/
135
+
136
+ # Vscode project settings
137
+ .vscode/
138
+
139
+ # Local user jupyter notebooks directory
140
+ notebooks/
141
+
142
+ # Mac OS stuff
143
+ .DS_Store
144
+
145
+ # Version
146
+ src/easylink/_version.py
147
+
148
+ # Local specification files
149
+ .specifications/
150
+
151
+ .snakemake/
@@ -0,0 +1,3 @@
1
+ **0.1.0 - 11/22/24**
2
+
3
+ - Initial release
@@ -0,0 +1,259 @@
1
+ def githubUsernameToSlackName(github_author) {
2
+ // Add team members as necessary
3
+ def mapping = [
4
+ "Jim Albright": "albrja",
5
+ "Steve Bachmeier": "sbachmei",
6
+ "Hussain Jafari": "hjafari",
7
+ "Patrick Nast": "pnast",
8
+ "Rajan Mudambi": "rmudambi",
9
+ ]
10
+ return mapping.get(github_author, "channel")
11
+ }
12
+
13
+ pipeline_name="easylink"
14
+ conda_env_name="${pipeline_name}-${BUILD_NUMBER}"
15
+ // using /tmp for things is MUCH faster but not shared between nodes.
16
+ shared_filesystem_path="/mnt/team/simulation_science/priv/engineering/tests"
17
+ conda_env_path="${shared_filesystem_path}/venv/${conda_env_name}"
18
+ // defaults for conda and pip are a local directory /svc-simsci for improved speed.
19
+ // In the past, we used /ihme/code/* on the NFS (which is slower)
20
+ shared_jenkins_node_path="/svc-simsci"
21
+
22
+ pipeline {
23
+ // This agent runs as svc-simsci on node simsci-slurm-sbuild-p01.
24
+ // It has access to standard IHME filesystems and singularity
25
+ agent { label "svc-simsci" }
26
+
27
+ options {
28
+ // Keep 100 old builds.
29
+ buildDiscarder logRotator(numToKeepStr: "100")
30
+
31
+ // Wait 60 seconds before starting the build.
32
+ // If another commit enters the build queue in this time, the first build will be discarded.
33
+ quietPeriod(60)
34
+
35
+ // Fail immediately if any part of a parallel stage fails
36
+ parallelsAlwaysFailFast()
37
+ }
38
+
39
+ parameters {
40
+ string(
41
+ name: "SLACK_TO",
42
+ defaultValue: "simsci-ci-status",
43
+ description: "The Slack channel to send messages to."
44
+ )
45
+ booleanParam(
46
+ name: "DEBUG",
47
+ defaultValue: false,
48
+ description: "Used as needed for debugging purposes."
49
+ )
50
+ }
51
+
52
+ environment {
53
+ // Get the branch being built and strip everything but the text after the last "/"
54
+ BRANCH = sh(script: "echo ${GIT_BRANCH} | rev | cut -d '/' -f1 | rev", returnStdout: true).trim()
55
+ TIMESTAMP = sh(script: 'date', returnStdout: true)
56
+ // Specify the path to the .condarc file via environment variable.
57
+ // This file configures the shared conda package cache.
58
+ CONDARC = "${shared_jenkins_node_path}/miniconda3/.condarc"
59
+ CONDA_BIN_PATH = "${shared_jenkins_node_path}/miniconda3/bin"
60
+ // Specify conda env by build number so that we don't have collisions if builds from
61
+ // different branches happen concurrently.
62
+ CONDA_ENV_NAME = "${conda_env_name}"
63
+ CONDA_ENV_PATH = "${conda_env_path}"
64
+ // Set the Pip cache.
65
+ XDG_CACHE_HOME = "${shared_jenkins_node_path}/pip-cache"
66
+ // Jenkins commands run in separate processes, so need to activate the environment every
67
+ // time we run pip, poetry, etc.
68
+ ACTIVATE = "source ${CONDA_BIN_PATH}/activate ${CONDA_ENV_PATH} &> /dev/null"
69
+ }
70
+
71
+ stages {
72
+ stage("Initialization") {
73
+ steps {
74
+ script {
75
+ // Use the name of the branch in the build name
76
+ currentBuild.displayName = "#${BUILD_NUMBER} ${GIT_BRANCH}"
77
+ // Tell BitBucket that a build has started.
78
+ notifyBitbucket()
79
+ }
80
+ }
81
+ }
82
+
83
+ stage("Debug Info") {
84
+ steps {
85
+ echo "Jenkins pipeline run timestamp: ${TIMESTAMP}"
86
+ // Display environment variables from Jenkins.
87
+ echo """Environment:
88
+ ACTIVATE: '${ACTIVATE}'
89
+ BUILD_NUMBER: '${BUILD_NUMBER}'
90
+ BRANCH: '${BRANCH}'
91
+ CONDARC: '${CONDARC}'
92
+ CONDA_BIN_PATH: '${CONDA_BIN_PATH}'
93
+ CONDA_ENV_NAME: '${CONDA_ENV_NAME}'
94
+ CONDA_ENV_PATH: '${CONDA_ENV_PATH}'
95
+ GIT_BRANCH: '${GIT_BRANCH}'
96
+ JOB_NAME: '${JOB_NAME}'
97
+ WORKSPACE: '${WORKSPACE}'
98
+ XDG_CACHE_HOME: '${XDG_CACHE_HOME}'"""
99
+ // display env
100
+ sh "env | sort"
101
+ }
102
+ }
103
+
104
+ stage("Build Environment") {
105
+ environment {
106
+ // Command for activating the base environment. Activating the base environment sets
107
+ // the correct path to the conda binary which is used to create a new conda env.
108
+ ACTIVATE_BASE = "source ${CONDA_BIN_PATH}/activate &> /dev/null"
109
+ }
110
+ steps {
111
+ // The env should have been cleaned out after the last build, but delete it again
112
+ // here just to be safe.
113
+ sh "rm -rf ${CONDA_ENV_PATH}"
114
+ sh "${ACTIVATE_BASE} && make build-env"
115
+ // open permissions for test users to create file in workspace
116
+ sh "chmod 777 ${WORKSPACE}"
117
+ }
118
+ }
119
+
120
+ stage("Install Package") {
121
+ steps {
122
+ // NOTE: If you're having issues with the env not being found, it's possible
123
+ // that 'make install' is generating symlinks. Try adding
124
+ // '&& pip install .' to install a second time w/ realpaths.
125
+ sh "${ACTIVATE} && make install && pip install ."
126
+ }
127
+ }
128
+
129
+ stage("Quality Checks") {
130
+ parallel {
131
+ stage("Format") {
132
+ steps {
133
+ sh "${ACTIVATE} && make format"
134
+ }
135
+ }
136
+
137
+ stage("Lint") {
138
+ steps {
139
+ sh "${ACTIVATE} && make lint"
140
+ }
141
+ }
142
+
143
+ stage("Type Check") {
144
+ steps {
145
+ sh "${ACTIVATE} && make typecheck"
146
+ }
147
+ }
148
+ }
149
+ }
150
+
151
+ stage("Test") {
152
+ parallel {
153
+ stage("Run End-to-End Tests") {
154
+ steps {
155
+ sh "${ACTIVATE} && make e2e"
156
+ publishHTML([
157
+ allowMissing: true,
158
+ alwaysLinkToLastBuild: false,
159
+ keepAll: true,
160
+ reportDir: "output/htmlcov_e2e",
161
+ reportFiles: "index.html",
162
+ reportName: "Coverage Report - E2E Tests",
163
+ reportTitles: ''
164
+ ])
165
+ }
166
+ }
167
+
168
+ stage("Run Integration Tests") {
169
+ steps {
170
+ sh "${ACTIVATE} && make integration"
171
+ publishHTML([
172
+ allowMissing: true,
173
+ alwaysLinkToLastBuild: false,
174
+ keepAll: true,
175
+ reportDir: "output/htmlcov_integration",
176
+ reportFiles: "index.html",
177
+ reportName: "Coverage Report - Integration Tests",
178
+ reportTitles: ''
179
+ ])
180
+ }
181
+ }
182
+
183
+ stage("Run Unit Tests") {
184
+ steps {
185
+ sh "${ACTIVATE} && make unit"
186
+ publishHTML([
187
+ allowMissing: true,
188
+ alwaysLinkToLastBuild: false,
189
+ keepAll: true,
190
+ reportDir: "output/htmlcov_unit",
191
+ reportFiles: "index.html",
192
+ reportName: "Coverage Report - Unit Tests",
193
+ reportTitles: ''
194
+ ])
195
+ }
196
+ }
197
+ }
198
+ }
199
+ }
200
+
201
+ post {
202
+ always {
203
+ script {
204
+ if (env.BRANCH == "main") {
205
+ channelName = "simsci-ci-status"
206
+ } else {
207
+ channelName = "simsci-ci-status-test"
208
+ }
209
+ // Run git command to get the author of the last commit
210
+ developerID = sh(
211
+ script: "git log -1 --pretty=format:'%an'",
212
+ returnStdout: true
213
+ ).trim()
214
+ slackID = githubUsernameToSlackName(developerID)
215
+ slackMessage = """
216
+ Job: *${env.JOB_NAME}*
217
+ Build number: #${env.BUILD_NUMBER}
218
+ Build status: *${currentBuild.result}*
219
+ Author: @${slackID}
220
+ Build details: <${env.BUILD_URL}/console|See in web console>
221
+ """.stripIndent()
222
+
223
+ // Must be after setting up slack message
224
+ if (params.DEBUG) {
225
+ echo "Debug is enabled. Not cleaning up."
226
+ } else {
227
+ echo "Cleaning up."
228
+ sh "${ACTIVATE} && make clean"
229
+ sh "rm -rf ${CONDA_ENV_PATH}"
230
+
231
+ // Delete the workspace directory.
232
+ deleteDir()
233
+ }
234
+ }
235
+
236
+ // Tell BitBucket whether the build succeeded or failed.
237
+ script {
238
+ notifyBitbucket()
239
+ }
240
+ }
241
+ failure {
242
+ slackSend channel: "#${params.SLACK_TO}",
243
+ message: slackMessage,
244
+ teamDomain: "ihme",
245
+ tokenCredentialId: "slack"
246
+ }
247
+ success {
248
+ script {
249
+ if (params.DEBUG) {
250
+ echo "Debug is enabled. Sending a success message to Slack."
251
+ slackSend channel: "#${params.SLACK_TO}",
252
+ message: slackMessage,
253
+ teamDomain: "ihme",
254
+ tokenCredentialId: "slack"
255
+ }
256
+ }
257
+ }
258
+ }
259
+ }
@@ -0,0 +1,101 @@
1
+ this_makefile := $(lastword $(MAKEFILE_LIST)) # Used to automatically list targets
2
+ .DEFAULT_GOAL := list # If someone runs "make", run "make list"
3
+
4
+ # Source files to format, lint, and type check.
5
+ LOCATIONS=src tests
6
+
7
+ # Unless overridden, build conda environment using the package name.
8
+ PACKAGE_NAME = easylink
9
+ SAFE_NAME = $(shell python -c "from pkg_resources import safe_name; print(safe_name(\"$(PACKAGE_NAME)\"))")
10
+
11
+ about_file = $(shell find src -name __about__.py)
12
+ version_file = $(shell find src -name _version.py)
13
+ version_line = $(shell grep "__version__ = " ${version_file})
14
+ PACKAGE_VERSION = $(shell echo ${version_line} | cut -d "=" -f 2 | xargs)
15
+
16
+ # Use this URL to pull IHME Python packages and deploy this package to PyPi.
17
+ IHME_PYPI := https://artifactory.ihme.washington.edu/artifactory/api/pypi/pypi-shared/
18
+
19
+ # If CONDA_ENV_PATH is set (from a Jenkins build), use the -p flag when making Conda env in
20
+ # order to make env at specific path. Otherwise, make a named env at the default path using
21
+ # the -n flag.
22
+ # TODO: [MIC-4953] build w/ multiple python versions
23
+ PYTHON_VERSION ?= 3.11
24
+ CONDA_ENV_NAME ?= ${PACKAGE_NAME}_py${PYTHON_VERSION}
25
+ CONDA_ENV_CREATION_FLAG = $(if $(CONDA_ENV_PATH),-p ${CONDA_ENV_PATH},-n ${CONDA_ENV_NAME})
26
+
27
+ # These are the doc and source code files in this repo.
28
+ # When one of these files changes, it means that Make targets need to run again.
29
+ MAKE_SOURCES := $(shell find . -type d -name "*" ! -path "./.git*" ! -path "./.vscode" ! -path "./output" ! -path "./output/*" ! -path "./archive" ! -path "./dist" ! -path "./output/htmlcov*" ! -path "**/.pytest_cache*" ! -path "**/__pycache__" ! -path "./output/docs_build*" ! -path "./.pytype*" ! -path "." ! -path "./src/${PACKAGE_NAME}/legacy*" ! -path ./.history ! -path "./.history/*" ! -path "./src/${PACKAGE_NAME}.egg-info" ! -path ./.idea ! -path "./.idea/*" )
30
+
31
+
32
+ # Phony targets don't produce artifacts.
33
+ .PHONY: .list-targets build-env clean debug deploy-doc deploy-package full help install list quick
34
+
35
+ # List of Make targets is generated dynamically. To add description of target, use a # on the target definition.
36
+ list help: debug .list-targets
37
+
38
+ .list-targets: # Print available Make targets
39
+ @echo
40
+ @echo "Make targets:"
41
+ @grep -i "^[a-zA-Z][a-zA-Z0-9_ \.\-]*: .*[#].*" ${this_makefile} | sort | sed 's/:.*#/ : /g' | column -t -s:
42
+ @echo
43
+
44
+ debug: # Print debug information (environment variables)
45
+ @echo "'make' invoked with these environment variables:"
46
+ @echo "CONDA_ENV_NAME: ${CONDA_ENV_NAME}"
47
+ @echo "IHME_PYPI: ${IHME_PYPI}"
48
+ @echo "LOCATIONS: ${LOCATIONS}"
49
+ @echo "PACKAGE_NAME: ${PACKAGE_NAME}"
50
+ @echo "PACKAGE_VERSION: ${PACKAGE_VERSION}"
51
+ @echo "PYPI_ARTIFACTORY_CREDENTIALS_USR: ${PYPI_ARTIFACTORY_CREDENTIALS_USR} "
52
+ @echo "Make sources: ${MAKE_SOURCES}"
53
+
54
+ build-env: # Make a new conda environment
55
+ @[ "${CONDA_ENV_NAME}" ] && echo "" > /dev/null || ( echo "CONDA_ENV_NAME is not set"; exit 1 )
56
+ conda create ${CONDA_ENV_CREATION_FLAG} python=${PYTHON_VERSION} --yes
57
+
58
+ install: # Install setuptools, install this package in editable mode
59
+ conda install python-graphviz
60
+ pip install --upgrade pip setuptools
61
+ pip install -e .[DEV]
62
+
63
+ format: setup.py pyproject.toml $(MAKE_SOURCES) # Run the code formatter and import sorter
64
+ -black $(LOCATIONS)
65
+ -isort $(LOCATIONS)
66
+ @echo "Ignore, Created by Makefile, `date`" > $@
67
+
68
+ lint: .flake8 .bandit $(MAKE_SOURCES) # Run the code linter and package security vulnerability checker
69
+ -flake8 $(LOCATIONS)
70
+ -safety check
71
+ @echo "Ignore, Created by Makefile, `date`" > $@
72
+
73
+ typecheck: pytype.cfg $(MAKE_SOURCES) # Run the type checker
74
+ -pytype --config=pytype.cfg $(LOCATIONS)
75
+ @echo "Ignore, Created by Makefile, `date`" > $@
76
+
77
+ e2e: $(MAKE_SOURCES) # Run the e2e tests
78
+ export COVERAGE_FILE=./output/.coverage.e2e
79
+ pytest -vvv --runslow --cov --cov-report term --cov-report html:./output/htmlcov_e2e tests/e2e/
80
+ @echo "Ignore, Created by Makefile, `date`" > $@
81
+
82
+ integration: $(MAKE_SOURCES) # Run unit tests
83
+ export COVERAGE_FILE=./output/.coverage.integration
84
+ pytest -vvv --runslow --cov --cov-report term --cov-report html:./output/htmlcov_integration tests/integration/
85
+ @echo "Ignore, Created by Makefile, `date`" > $@
86
+
87
+ unit: $(MAKE_SOURCES) # Run unit tests
88
+ export COVERAGE_FILE=./output/.coverage.unit
89
+ pytest -vvv --runslow --cov --cov-report term --cov-report html:./output/htmlcov_unit tests/unit/
90
+ @echo "Ignore, Created by Makefile, `date`" > $@
91
+
92
+ clean: # Delete build artifacts and do any custom cleanup such as spinning down services
93
+ @rm -rf format lint typecheck build-doc build-package unit e2e integration .pytest_cache .pytype
94
+ @rm -rf dist output
95
+ $(shell find . -type f -name '*py[co]' -delete -o -type d -name __pycache__ -delete)
96
+
97
+ quick: # Run a "quick" build
98
+ $(MAKE) format lint typecheck unit build-doc
99
+
100
+ full: clean # Run a "full" build
101
+ $(MAKE) install quick e2e build-package