Skip to content

Commit 8a27c0c

Browse files
authored
Merge pull request #1001 from Sage-Bionetworks/develop
Release 22.11.1
2 parents 4881d81 + 77b6032 commit 8a27c0c

File tree

10 files changed

+283
-20
lines changed

10 files changed

+283
-20
lines changed

.github/workflows/pdoc.yml

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
name: pdoc
2+
3+
# build the documentation whenever there are new commits on main
4+
on:
5+
push:
6+
branches:
7+
- develop
8+
workflow_dispatch: # Allow manually triggering the workflow
9+
10+
# security: restrict permissions for CI jobs.
11+
permissions:
12+
contents: read
13+
14+
concurrency:
15+
# cancel the current running workflow from the same branch, PR when a new workflow is triggered
16+
# when the trigger is not a PR but a push, it will use the commit sha to generate the concurrency group
17+
# {{ github.workflow }}: the workflow name is used to generate the concurrency group. This allows you to have more than one workflows
18+
# {{ github.ref_type }}: the type of Git ref object created in the repository. Can be either branch or tag
19+
# {{ github.event.pull_request.number}}: get PR number
20+
# {{ github.sha }}: full commit sha
21+
# credit: https://github.com/Sage-Bionetworks-Workflows/sagetasks/blob/main/.github/workflows/ci.yml
22+
group: >-
23+
${{ github.workflow }}-${{ github.ref_type }}-
24+
${{ github.event.pull_request.number || github.sha }}
25+
cancel-in-progress: true
26+
jobs:
27+
build:
28+
runs-on: ubuntu-latest
29+
env:
30+
POETRY_VERSION: 1.2.0
31+
strategy:
32+
matrix:
33+
python-version: ["3.9", "3.10"]
34+
35+
steps:
36+
#----------------------------------------------
37+
# check-out repo and set-up python
38+
#----------------------------------------------
39+
- name: Check out repository
40+
uses: actions/checkout@v3
41+
42+
- name: Set up Python ${{ matrix.python-version }}
43+
uses: actions/setup-python@v3
44+
with:
45+
python-version: ${{ matrix.python-version }}
46+
47+
#----------------------------------------------
48+
# install & configure poetry
49+
#----------------------------------------------
50+
- name: Install Poetry
51+
run: |
52+
curl -sSL https://install.python-poetry.org \
53+
| python3 - --version ${{ env.POETRY_VERSION }};
54+
poetry config virtualenvs.create true;
55+
poetry config virtualenvs.in-project true;
56+
57+
#----------------------------------------------
58+
# load cached venv if cache exists
59+
#----------------------------------------------
60+
- name: Load cached venv
61+
id: cached-poetry-dependencies
62+
uses: actions/cache@v3
63+
with:
64+
path: .venv
65+
key: venv-${{ runner.os }}-${{ hashFiles('**/poetry.lock') }}
66+
67+
#----------------------------------------------
68+
# install dependencies if cache does not exist
69+
#----------------------------------------------
70+
- name: Install dependencies
71+
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
72+
run: poetry install --no-interaction --no-root
73+
74+
# create documentation
75+
- run: poetry show pdoc
76+
- run: poetry run pdoc --docformat google -o docs/schematic schematic/manifest schematic/models schematic/schemas schematic/store schematic/utils schematic/visualization
77+
78+
- uses: actions/upload-pages-artifact@v1
79+
with:
80+
path: docs/schematic
81+
82+
# Deploy the artifact to GitHub pages.
83+
# This is a separate job so that only actions/deploy-pages has the necessary permissions.
84+
deploy:
85+
needs: build
86+
runs-on: ubuntu-latest
87+
permissions:
88+
pages: write
89+
id-token: write
90+
environment:
91+
name: github-pages
92+
url: ${{ steps.deployment.outputs.page_url }}
93+
steps:
94+
- id: deployment
95+
uses: actions/deploy-pages@v1

README.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,72 @@ For new features, bugs, enhancements
179179

180180
*Note*: Make sure you have the latest version of the `develop` branch on your local machine.
181181

182+
## Installation Guide - Docker
183+
184+
1. Install docker from https://www.docker.com/ . <br>
185+
2. Identify docker image of interest from [Schematic DockerHub](https://hub.docker.com/r/sagebionetworks/schematic/tags) <br>
186+
Ex `docker pull sagebionetworks/schematic:latest` from the CLI or, run `docker compose up` after cloning the schematic github repo <br>
187+
in this case, `sagebionetworks/schematic:latest` is the name of the image chosen
188+
3. Run Schematic Command with `docker run <flags> <schematic command and args>`. <br>
189+
<t> - For more information on flags for `docker run` and what they do, visit the [Docker Documentation](https://docs.docker.com/engine/reference/commandline/run/) <br>
190+
<t> - These example commands assume that you have navigated to the directory you want to run schematic from. To specify your working directory, use `$(pwd)` on MacOS/Linux or `%cd%` on Windows. <br>
191+
<t> - If not using the latest image, then the full name should be specified: ie `sagebionetworks/schematic:commit-e611e4a` <br>
192+
<t> - If using local image created by `docker compose up`, then the docker image name should be changed: i.e. `schematic_schematic` <br>
193+
<t> - Using the `--name` flag sets the name of the container running locally on your machine <br>
194+
195+
### Example For REST API <br>
196+
197+
#### Use file path of `config.yml` to run API endpoints:
198+
```
199+
docker run --rm -p 3001:3001 \
200+
-v $(pwd):/schematic -w /schematic --name schematic \
201+
-e SCHEMATIC_CONFIG=/schematic/config.yml \
202+
-e GE_HOME=/usr/src/app/great_expectations/ \
203+
sagebionetworks/schematic \
204+
python /usr/src/app/run_api.py
205+
```
206+
207+
#### Use content of `config.yml` as an environment variable to run API endpoints:
208+
1. save content of `config.yml` as to environment variable `SCHEMATIC_CONFIG_CONTENT` by doing: `export SCHEMATIC_CONFIG_CONTENT=$(cat config.yml)`
209+
210+
2. Pass `SCHEMATIC_CONFIG_CONTENT` as an environment variable by using `docker run`
211+
212+
```
213+
docker run --rm -p 3001:3001 \
214+
-v $(pwd):/schematic -w /schematic --name schematic \
215+
-e GE_HOME=/usr/src/app/great_expectations/ \
216+
-e SCHEMATIC_CONFIG_CONTENT=$SCHEMATIC_CONFIG_CONTENT \
217+
sagebionetworks/schematic \
218+
python /usr/src/app/run_api.py
219+
```
220+
221+
222+
### Example For Schematic on mac/linux <br>
223+
To run example below, first clone schematic into your home directory `git clone https://github.com/sage-bionetworks/schematic ~/schematic` <br>
224+
Then update .synapseConfig with your credentials
225+
```
226+
docker run \
227+
-v ~/schematic:/schematic \
228+
-w /schematic \
229+
-e SCHEMATIC_CONFIG=/schematic/config.yml \
230+
-e GE_HOME=/usr/src/app/great_expectations/ \
231+
sagebionetworks/schematic schematic model \
232+
-c /schematic/config.yml validate \
233+
-mp /schematic/tests/data/mock_manifests/Valid_Test_Manifest.csv \
234+
-dt MockComponent \
235+
-js /schematic/tests/data/example.model.jsonld
236+
```
237+
238+
### Example For Schematic on Windows <br>
239+
```
240+
docker run -v %cd%:/schematic \
241+
-w /schematic \
242+
-e GE_HOME=/usr/src/app/great_expectations/ \
243+
sagebionetworks/schematic \
244+
schematic model \
245+
-c config.yml validate -mp tests/data/mock_manifests/inValid_Test_Manifest.csv -dt MockComponent -js /schematic/data/example.model.jsonld
246+
```
247+
182248
# Other Contribution Guidelines
183249
## Updating readthedocs documentation
184250
1. `cd docs`

api/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ def create_app():
1515
# path to config.yml file saved as a Flask config variable
1616
default_config = os.path.abspath(os.path.join(__file__, "../../config.yml"))
1717
schematic_config = os.environ.get("SCHEMATIC_CONFIG", default_config)
18+
schematic_config_content = os.environ.get("SCHEMATIC_CONFIG_CONTENT")
19+
1820
app.config["SCHEMATIC_CONFIG"] = schematic_config
21+
app.config["SCHEMATIC_CONFIG_CONTENT"] = schematic_config_content
1922

2023
# Configure flask app
2124
# app.config[] = schematic[]

api/routes.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,14 @@
3737
def config_handler(asset_view=None):
3838
path_to_config = app.config["SCHEMATIC_CONFIG"]
3939

40-
# check if file exists at the path created, i.e., app.config['SCHEMATIC_CONFIG']
40+
# if content of the config file is provided:
41+
content_of_config = app.config["SCHEMATIC_CONFIG_CONTENT"]
42+
43+
# if the environment variable exists
44+
if content_of_config:
45+
CONFIG.load_config_content_from_env()
46+
47+
# check if path to config is provided
4148
if os.path.isfile(path_to_config):
4249
CONFIG.load_config(path_to_config, asset_view = asset_view)
4350

docker-compose.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ services:
1313
APP_HOST: "0.0.0.0"
1414
APP_PORT: "3001"
1515
SCHEMATIC_CONFIG: /schematic/config.yml
16+
SCHEMATIC_CONFIG_CONTENT: "${SCHEMATIC_CONFIG_CONTENT}"
1617
GE_HOME: /usr/src/app/great_expectations/

poetry.lock

Lines changed: 53 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ Jinja2 = "2.11.3"
6666
openpyxl = "^3.0.9"
6767
"backports.zoneinfo" = {markers = "python_version < \"3.9\"", version = "^0.2.1"}
6868
Flask-Cors = "^3.0.10"
69+
pdoc = "^12.2.0"
6970

7071

7172
[tool.poetry.dev-dependencies]

schematic/configuration.py

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,16 @@ def __init__(self):
99
# entire configuration data
1010
self.DATA = None
1111

12+
1213
def __getattribute__(self, name):
1314
value = super().__getattribute__(name)
14-
if value is None and "SCHEMATIC_CONFIG" in os.environ:
15+
if value is None and "SCHEMATIC_CONFIG_CONTENT" in os.environ:
16+
self.load_config_content_from_env()
17+
value = super().__getattribute__(name)
18+
elif value is None and "SCHEMATIC_CONFIG" in os.environ:
1519
self.load_config_from_env()
1620
value = super().__getattribute__(name)
17-
elif value is None and "SCHEMATIC_CONFIG" not in os.environ:
21+
elif value is None and "SCHEMATIC_CONFIG" not in os.environ and "SCHEMATIC_CONFIG_CONTENT" not in os.environ:
1822
raise AttributeError(
1923
"The '%s' configuration field was accessed, but it hasn't been "
2024
"set yet, presumably because the schematic.CONFIG.load_config() "
@@ -34,6 +38,14 @@ def get(self, key, default):
3438
value = default
3539
return value
3640

41+
def load_config_content(self, str_yaml: str) -> dict:
42+
try:
43+
config_data = yaml.safe_load(str_yaml)
44+
except yaml.YAMLError as exc:
45+
print(exc)
46+
return None
47+
return config_data
48+
3749
@staticmethod
3850
def load_yaml(file_path: str) -> dict:
3951
with open(file_path, "r") as stream:
@@ -45,9 +57,15 @@ def load_yaml(file_path: str) -> dict:
4557
return config_data
4658

4759
def normalize_path(self, path):
48-
# Retrieve parent directory of the config to decode relative paths
49-
parent_dir = os.path.dirname(self.CONFIG_PATH)
50-
# Ensure absolute file paths
60+
61+
if self.CONFIG_PATH:
62+
# Retrieve parent directory of the config to decode relative paths
63+
parent_dir = os.path.dirname(self.CONFIG_PATH)
64+
else:
65+
# assume the parent dir would be the current work dir
66+
parent_dir = os.getcwd()
67+
68+
# Ensure absolute file paths
5169
if not os.path.isabs(path):
5270
path = os.path.join(parent_dir, path)
5371
# And lastly, normalize file paths
@@ -61,7 +79,19 @@ def load_config_from_env(self):
6179
)
6280
return self.load_config(schematic_config)
6381

64-
def load_config(self, config_path=None, asset_view=None):
82+
def load_config_content_from_env(self):
83+
schematic_config_content = os.environ["SCHEMATIC_CONFIG_CONTENT"]
84+
85+
print(
86+
'Loading content of config file: %s' % schematic_config_content
87+
)
88+
89+
config_content_yaml = self.load_config_content(schematic_config_content)
90+
self.DATA = config_content_yaml
91+
92+
return self.DATA
93+
94+
def load_config(self, config_path=None, asset_view=None):
6595
# If config_path is None, try loading from environment
6696
if config_path is None and "SCHEMATIC_CONFIG" in os.environ:
6797
return self.load_config_from_env()

0 commit comments

Comments
 (0)