Skip to content

Commit 0aa2738

Browse files
authored
🔨 Changes developmental releases strategy (#180)
1 parent 6c4e055 commit 0aa2738

File tree

10 files changed

+110
-21
lines changed

10 files changed

+110
-21
lines changed

‎.gitignore‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,8 @@ tmp*
8989
*ignore*
9090
!.dockerignore
9191
!.gitignore
92+
93+
94+
# api diffs
95+
api/openapi-*-diff.json
96+
api/openapi-dev.json

‎api/Makefile‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
include ../scripts/common.Makefile
2+
3+
4+
.PHONY: openapi-diff-dev.json
5+
openapi-dev-diff.json: ## Diffs against newer openapi-dev.json and checks backwards compatibility
6+
$(SCRIPTS_DIR)/openapi-diff.bash \
7+
/specs/openapi.json \
8+
/specs/openapi-dev.json \
9+
--fail-on-incompatible \
10+
--json=/specs/$@
11+
12+
13+
14+
.PHONY: openapi-diff-dev.json
15+
openapi-deploy-diff.json: ## Diffs against newer openapi-dev.json and checks backwards compatibility
16+
$(SCRIPTS_DIR)/openapi-diff.bash \
17+
https://api.osparc.io/api/v0/openapi.json \
18+
/specs/openapi.json \
19+
--fail-on-incompatible \
20+
--json=/specs/$@

‎clients/python/src/osparc/_files_api.py‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,16 @@
2929
PaginationGenerator,
3030
compute_sha256,
3131
file_chunk_generator,
32+
dev_features_enabled,
3233
)
3334

3435
_logger = logging.getLogger(__name__)
3536

3637

3738
class FilesApi(_FilesApi):
38-
"""Class for interacting with files"""
39+
_dev_features = [
40+
"get_jobs_page",
41+
]
3942

4043
def __init__(self, api_client: ApiClient):
4144
"""Construct object
@@ -52,6 +55,11 @@ def __init__(self, api_client: ApiClient):
5255
else None
5356
)
5457

58+
def __getattr__(self, name: str) -> Any:
59+
if (name in FilesApi._dev_features) and (not dev_features_enabled()):
60+
raise NotImplementedError(f"FilesApi.{name} is still under development")
61+
return super().__getattribute__(name)
62+
5563
def download_file(
5664
self, file_id: str, *, destination_folder: Optional[Path] = None, **kwargs
5765
) -> str:

‎clients/python/src/osparc/_solvers_api.py‎

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
dev_features_enabled,
1515
)
1616

17+
import warnings
18+
1719

1820
class SolversApi(_SolversApi):
1921
"""Class for interacting with solvers"""
@@ -22,11 +24,6 @@ class SolversApi(_SolversApi):
2224
"get_jobs_page",
2325
]
2426

25-
def __getattr__(self, name: str) -> Any:
26-
if (name in SolversApi._dev_features) and (not dev_features_enabled()):
27-
raise NotImplementedError(f"SolversApi.{name} is still under development")
28-
return super().__getattribute__(name)
29-
3027
def __init__(self, api_client: ApiClient):
3128
"""Construct object
3229
@@ -42,6 +39,11 @@ def __init__(self, api_client: ApiClient):
4239
else None
4340
)
4441

42+
def __getattr__(self, name: str) -> Any:
43+
if (name in SolversApi._dev_features) and (not dev_features_enabled()):
44+
raise NotImplementedError(f"SolversApi.{name} is still under development")
45+
return super().__getattribute__(name)
46+
4547
def list_solver_ports(
4648
self, solver_key: str, version: str, **kwargs
4749
) -> List[SolverPort]:
@@ -51,7 +53,7 @@ def list_solver_ports(
5153
return page.items if page.items else []
5254

5355
@dev_feature
54-
def jobs(self, solver_key: str, version: str) -> PaginationGenerator:
56+
def iter_jobs(self, solver_key: str, version: str, **kwargs) -> PaginationGenerator:
5557
"""Returns an iterator through which one can iterate over
5658
all Jobs submitted to the solver
5759
@@ -73,6 +75,7 @@ def _pagination_method():
7375
version=version,
7476
limit=_DEFAULT_PAGINATION_LIMIT,
7577
offset=_DEFAULT_PAGINATION_OFFSET,
78+
**kwargs,
7679
)
7780

7881
return PaginationGenerator(
@@ -82,6 +85,16 @@ def _pagination_method():
8285
auth=self._auth,
8386
)
8487

88+
@dev_feature
89+
def jobs(self, solver_key: str, version: str, **kwargs) -> PaginationGenerator:
90+
warnings.warn(
91+
"The 'jobs' method is deprecated and will be removed in a future version. "
92+
"Please use 'iter_jobs' instead.",
93+
DeprecationWarning,
94+
stacklevel=2,
95+
)
96+
return self.iter_jobs(solver_key, version, **kwargs)
97+
8598
def create_job(
8699
self, solver_key: str, version: str, job_inputs: JobInputs, **kwargs
87100
):

‎clients/python/src/osparc/_studies_api.py‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
PaginationGenerator,
1919
dev_features_enabled,
2020
)
21+
import warnings
2122

2223
_logger = logging.getLogger(__name__)
2324

@@ -68,7 +69,7 @@ def clone_study(self, study_id: str, **kwargs):
6869
kwargs = {**kwargs, **ParentProjectInfo().model_dump(exclude_none=True)}
6970
return super().clone_study(study_id, **kwargs)
7071

71-
def studies(self, **kwargs) -> PaginationGenerator:
72+
def iter_studies(self, **kwargs) -> PaginationGenerator:
7273
def _pagination_method():
7374
page_study = self.list_studies(
7475
limit=_DEFAULT_PAGINATION_LIMIT,
@@ -85,6 +86,15 @@ def _pagination_method():
8586
auth=self._auth,
8687
)
8788

89+
def studies(self, **kwargs) -> PaginationGenerator:
90+
warnings.warn(
91+
"The 'studies' method is deprecated and will be removed in a future version. "
92+
"Please use 'iter_studies' instead.",
93+
DeprecationWarning,
94+
stacklevel=2,
95+
)
96+
return self.iter_studies(**kwargs)
97+
8898
def get_study_job_output_logfiles(self, study_id: str, job_id: str) -> Path:
8999
return asyncio.run(
90100
self.get_study_job_output_logfiles_async(study_id=study_id, job_id=job_id)

‎clients/python/test/e2e/ci/e2e/e2e/postprocess.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ def clean_up_jobs(artifacts_dir: Path, retry_minutes: Optional[PositiveInt] = No
239239
assert isinstance(solver, osparc.Solver)
240240
assert (id_ := solver.id) is not None
241241
assert (version := solver.version) is not None
242-
for job in solvers_api.jobs(id_, version):
242+
for job in solvers_api.iter_jobs(id_, version):
243243
assert isinstance(job, osparc.Job)
244244
solvers_api.delete_job(id_, version, job.id)
245245
except RetryError as exc:

‎clients/python/test/e2e/conftest.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ def sleeper_study_id(api_client: osparc.ApiClient) -> UUID:
164164
as input a single file containing a single integer"""
165165
_test_study_title = "sleeper_test_study"
166166
study_api = osparc.StudiesApi(api_client=api_client)
167-
for study in study_api.studies():
167+
for study in study_api.iter_studies():
168168
if study.title == _test_study_title:
169169
return UUID(study.uid)
170170
pytest.fail(f"Could not find {_test_study_title} study")

‎clients/python/test/e2e/test_solvers_api.py‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def test_jobs(api_client: osparc.ApiClient, sleeper: osparc.Solver):
2424
n_jobs: int = 3
2525
solvers_api = osparc.SolversApi(api_client=api_client)
2626
# initial iterator
27-
init_iter = solvers_api.jobs(sleeper.id, sleeper.version)
27+
init_iter = solvers_api.iter_jobs(sleeper.id, sleeper.version)
2828
n_init_iter: int = len(init_iter)
2929
assert n_init_iter >= 0
3030

@@ -36,10 +36,10 @@ def test_jobs(api_client: osparc.ApiClient, sleeper: osparc.Solver):
3636
)
3737
created_job_ids.append(job.id)
3838

39-
tmp_iter = solvers_api.jobs(sleeper.id, sleeper.version)
40-
solvers_api.jobs(sleeper.id, sleeper.version)
39+
tmp_iter = solvers_api.iter_jobs(sleeper.id, sleeper.version)
40+
solvers_api.iter_jobs(sleeper.id, sleeper.version)
4141

42-
final_iter = solvers_api.jobs(sleeper.id, sleeper.version)
42+
final_iter = solvers_api.iter_jobs(sleeper.id, sleeper.version)
4343
assert len(final_iter) > 0, "No jobs were available"
4444
assert n_init_iter + n_jobs == len(
4545
final_iter

‎scripts/generate_version.bash‎

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,30 @@ set -o pipefail # don't hide errors within pipes
1010
trap "{ echo 'Could not generate a version file. Probably you need to sync your fork.' >&2; }" ERR
1111

1212
release_info=$(git ls-remote --tags --refs --sort=version:refname https://github.com/ITISFoundation/osparc-simcore-clients | tail -1)
13-
release_version=$(echo "${release_info}" | grep -oP '(?<=refs/tags/v)\d+\.\d+\.\d+')
14-
release_commit=$(echo "${release_info}" | grep -oE '^[[:alnum:]]+')
13+
released_version=$(echo "${release_info}" | grep -oP '(?<=refs/tags/v)\d+\.\d+\.\d+')
14+
released_commit=$(echo "${release_info}" | grep -oE '^[[:alnum:]]+')
1515
current_commit=$(git rev-parse HEAD)
1616

17-
#
18-
# Determines how many commits since the last release and adds that as `post` index.
19-
# WARNING: we should change Version Scheme to https://packaging.python.org/en/latest/specifications/version-specifiers/#version-scheme
20-
merge_base=$(git merge-base "${release_commit}" "${current_commit}")
17+
18+
# Determines how many commits since the last release and adds that as `dev` index.
19+
merge_base=$(git merge-base "${released_commit}" "${current_commit}")
2120
n_commits_to_merge_base=$(git rev-list --count "${merge_base}".."${current_commit}")
22-
echo -n "${release_version}.post${n_commits_to_merge_base}"
21+
22+
23+
# NOTE:
24+
# - we develop using post-release versioning
25+
# - i.e. 1.2.3.post3.devN where N is the number of commits with respect to last release 1.2.3)
26+
# - Another approach would be using a pre-release version but we do not want to decide on that version
27+
# - the releases are of the type 1.2.3
28+
# - we never do post releases as 1.2.3.postX but instead use patches i.e. 1.2.4
29+
# - the releases are defined using git tags (that is the case with n_commits_to_merge_base=0 )
30+
# - SEE .github/workflows/publish-python-client.yml for more details
31+
#
32+
if [ "$n_commits_to_merge_base" -gt 0 ]; then
33+
echo "${released_version}.post3.dev${n_commits_to_merge_base}"
34+
elif [ "$n_commits_to_merge_base" -eq 0 ]; then
35+
echo "${released_version}"
36+
else
37+
echo "Error: n_commits_to_merge_base is negative. This should not happen." >&2
38+
exit 1
39+
fi

‎scripts/openapi-diff.bash‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/bin/bash
2+
#
3+
#
4+
# - https://github.com/OpenAPITools/openapi-diff
5+
#
6+
# NOTE: do not forget that the target /specs
7+
8+
exec docker run \
9+
--interactive \
10+
--rm \
11+
--volume="/etc/group:/etc/group:ro" \
12+
--volume="/etc/passwd:/etc/passwd:ro" \
13+
--user="$(id --user "$USER")":"$(id --group "$USER")" \
14+
--volume "$(pwd):/specs" \
15+
openapitools/openapi-diff:latest \
16+
"$@"

0 commit comments

Comments
 (0)