Skip to content

Commit ef13578

Browse files
authored
Script-assisted release process proposal (#1421)
* clean up verify license * fix licenses in place * add license to examples * freeze ci version script * lint pass * add make targets for making a release and starting a new dev cycle * update fetch_contributors so that it updates the CONTRIBUTORS.md * adding in bump version number script * dev1 stripping/appending script * add confirmation to makefile * omit the otio-version json from the packages * rename bump version target to be specific to minor version bumps * add shuffle verison map * add dev-suffix target * add test-core Co-authored-by: ssteinbach <[email protected]>
1 parent 3703ac7 commit ef13578

File tree

11 files changed

+655
-34
lines changed

11 files changed

+655
-34
lines changed

MANIFEST.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ exclude contrib/opentimelineio_contrib/adapters/Makefile
2222
exclude Makefile
2323
exclude */.DS_Store
2424
exclude .clang-format
25+
exclude OTIO_VERSION.json
2526
global-exclude *.pyc
2627

2728
prune maintainers

Makefile

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ CLANG_FORMAT_PROG := $(shell command -v clang-format 2> /dev/null)
3333
# AUTOPEP8_PROG := $(shell command -v autopep8 2> /dev/null)
3434
TEST_ARGS=
3535

36+
GIT = git
37+
GITSTATUS := $(shell git diff-index --quiet HEAD . 1>&2 2> /dev/null; echo $$?)
38+
39+
3640
ifeq ($(VERBOSE), 1)
3741
TEST_ARGS:=-v
3842
endif
@@ -187,6 +191,7 @@ version-map:
187191
@python src/py-opentimelineio/opentimelineio/console/autogen_version_map.py -i src/opentimelineio/CORE_VERSION_MAP.last.cpp --dryrun
188192

189193
version-map-update:
194+
@echo "updating the CORE_VERSION_MAP..."
190195
@python src/py-opentimelineio/opentimelineio/console/autogen_version_map.py -i src/opentimelineio/CORE_VERSION_MAP.last.cpp -o src/opentimelineio/CORE_VERSION_MAP.cpp
191196

192197
# generate documentation in html
@@ -198,3 +203,95 @@ doc-cpp:
198203
@cd doxygen ; doxygen config/dox_config ; cd ..
199204
@echo "wrote doxygen output to: doxygen/output/html/index.html"
200205

206+
# release related targets
207+
confirm-release-intent:
208+
ifndef OTIO_DO_RELEASE
209+
$(error \
210+
"If you are sure you want to perform a release, set OTIO_DO_RELEASE=1")
211+
endif
212+
@echo "Starting release process..."
213+
214+
check-git-status:
215+
ifneq ($(GITSTATUS), 0)
216+
$(error \
217+
"Git repository is dirty, cannot create release. Run 'git status' \
218+
for more info")
219+
endif
220+
@echo "Git status is clean, ready to proceed with release."
221+
222+
verify-license:
223+
@echo "Verifying licenses in files..."
224+
@python maintainers/verify_license.py -s .
225+
226+
fix-license:
227+
@python maintainers/verify_license.py -s . -f
228+
229+
freeze-ci-versions:
230+
@echo "freezing CI versions..."
231+
@python maintainers/freeze_ci_versions.py -f
232+
233+
unfreeze-ci-versions:
234+
@echo "unfreezing CI versions..."
235+
@python maintainers/freeze_ci_versions.py -u
236+
237+
# needs to happen _before_ version-map-update so that version in
238+
# CORE_VERSION_MAP does not have the .dev1 suffix at release time
239+
remove-dev-suffix:
240+
@echo "Removing .dev1 suffix"
241+
@python maintainers/remove_dev_suffix.py -r
242+
243+
check-github-token:
244+
ifndef OTIO_RELEASE_GITHUB_TOKEN
245+
$(error \
246+
OTIO_RELEASE_GITHUB_TOKEN is not set, unable to update contributors)
247+
endif
248+
249+
update-contributors: check-github-token
250+
@echo "Updating CONTRIBUTORS.md..."
251+
@python maintainers/fetch_contributors.py \
252+
--repo AcademySoftwareFoundation/OpenTimelineIO \
253+
--token $(OTIO_RELEASE_GITHUB_TOKEN)
254+
255+
dev-python-install:
256+
@python setup.py install
257+
258+
# make target for preparing a release candidate
259+
release: \
260+
confirm-release-intent \
261+
check-git-status \
262+
check-github-token \
263+
verify-license \
264+
freeze-ci-versions \
265+
remove-dev-suffix \
266+
format \
267+
dev-python-install \
268+
version-map-update \
269+
test-core \
270+
update-contributors
271+
@echo "Release is ready. Commit, push and open a PR!"
272+
273+
# targets for creating a new version (after making a release, to start the next
274+
# development cycle)
275+
bump-otio-minor-version:
276+
@python maintainers/bump_version_number.py -i minor
277+
278+
shuffle-core-version-map:
279+
@cp -f src/opentimelineio/CORE_VERSION_MAP.cpp \
280+
src/opentimelineio/CORE_VERSION_MAP.last.cpp
281+
@echo "set the current version map as the next one"
282+
283+
add-dev-suffix:
284+
@echo "Adding .dev1 suffix"
285+
@python maintainers/remove_dev_suffix.py -a
286+
287+
# make target for starting a new version (after a release is completed)
288+
start-dev-new-minor-version: \
289+
check-git-status \
290+
unfreeze-ci-versions \
291+
bump-otio-minor-version \
292+
shuffle-core-version-map \
293+
add-dev-suffix \
294+
dev-python-install \
295+
version-map-update \
296+
test-core
297+
@echo "New version made. Commit, push and open a PR!"

OTIO_VERSION.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"version": ["0", "15", "0"]}

examples/sample_plugin/otio_counter/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
# Copyright Contributors to the OpenTimelineIO project
13
import pkg_resources
24

35
from opentimelineio.plugins import manifest

examples/sample_plugin/otio_counter/adapter.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
# Copyright Contributors to the OpenTimelineIO project
13
import opentimelineio as otio
24

35
"""

examples/sample_plugin/setup.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
# Copyright Contributors to the OpenTimelineIO project
13
from setuptools import setup
24

35
"""

maintainers/bump_version_number.py

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
#!/usr/bin/env python
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
# Copyright Contributors to the OpenTimelineIO project
5+
6+
__doc__ = """Manage and apply the version in the OTIO_VERSION.json file"""
7+
8+
import argparse
9+
import sys
10+
import json
11+
12+
OTIO_VERSION_JSON_PATH = "OTIO_VERSION.json"
13+
14+
15+
def version():
16+
with open(OTIO_VERSION_JSON_PATH, 'r') as fi:
17+
return json.load(fi)['version']
18+
19+
20+
def _parsed_args():
21+
parser = argparse.ArgumentParser(
22+
description='Fetch a list of contributors for a given GitHub repo.'
23+
)
24+
25+
op_grp = parser.add_mutually_exclusive_group(required=True)
26+
op_grp.add_argument(
27+
"-i",
28+
"--increment",
29+
type=str,
30+
default=None,
31+
choices=("major", "minor", "patch"),
32+
help="Increment either the major or minor version number."
33+
)
34+
op_grp.add_argument(
35+
"-s",
36+
"--set",
37+
type=str,
38+
default=None,
39+
nargs=3,
40+
help="Set the version string, in the form of MAJOR MINOR PATCH"
41+
)
42+
op_grp.add_argument(
43+
"-q",
44+
"--query",
45+
default=False,
46+
action="store_true",
47+
help="Query/print the current version without changing it"
48+
)
49+
parser.add_argument(
50+
"-d",
51+
"--dryrun",
52+
default=False,
53+
action="store_true",
54+
help="Perform actions but modify no files on disk."
55+
)
56+
return parser.parse_args()
57+
58+
59+
def main():
60+
args = _parsed_args()
61+
62+
major, minor, patch = (int(v) for v in version())
63+
64+
if args.increment == "major":
65+
major += 1
66+
minor = 0
67+
patch = 0
68+
elif args.increment == "minor":
69+
minor += 1
70+
patch = 0
71+
elif args.increment == "patch":
72+
patch += 1
73+
elif args.set:
74+
major, minor, patch = args.set
75+
elif args.query:
76+
print(".".join(str(v) for v in (major, minor, patch)))
77+
return
78+
79+
print("Setting version to: {}.{}.{}".format(major, minor, patch))
80+
81+
# update the OTIO_VERSION file
82+
with open(OTIO_VERSION_JSON_PATH, "w") as fo:
83+
fo.write(
84+
json.dumps({"version": [str(v) for v in (major, minor, patch)]})
85+
)
86+
print("Updated {}".format(OTIO_VERSION_JSON_PATH))
87+
88+
# update the CMakeLists.txt
89+
with open("CMakeLists.txt", 'r') as fi:
90+
cmake_input = fi.read()
91+
92+
cmake_output = []
93+
key_map = {"MAJOR": major, "MINOR": minor, "PATCH": patch}
94+
for ln in cmake_input.split("\n"):
95+
for label, new_value in key_map.items():
96+
if "set(OTIO_VERSION_{} \"".format(label) in ln:
97+
cmake_output.append(
98+
"set(OTIO_VERSION_{} \"{}\")".format(label, new_value)
99+
)
100+
break
101+
else:
102+
cmake_output.append(ln)
103+
104+
with open("CMakeLists.txt", 'w') as fo:
105+
fo.write("\n".join(cmake_output))
106+
print("Updated {}".format("CMakeLists.txt"))
107+
108+
# update the setup.py
109+
with open("setup.py", 'r') as fi:
110+
setup_input = fi.read()
111+
112+
setup_output = []
113+
for ln in setup_input.split("\n"):
114+
if "\"version\": " in ln:
115+
116+
setup_output.append(
117+
" \"version\": \"{}.{}.{}{}\",".format(
118+
major,
119+
minor,
120+
patch,
121+
(".dev1" in ln) and ".dev1" or ""
122+
)
123+
)
124+
else:
125+
setup_output.append(ln)
126+
127+
with open("setup.py", 'w') as fo:
128+
fo.write("\n".join(setup_output))
129+
print("Updated {}".format("setup.py"))
130+
131+
132+
def add_suffix(content, version):
133+
if version not in content:
134+
sys.stderr.write(
135+
"Version {} not found, suffix may have already been "
136+
"added.\n".format(version)
137+
)
138+
return False
139+
140+
print("adding suffix, version will be: {}".format(version + ".dev1"))
141+
content.replace(version, version + ".dev1")
142+
return True
143+
144+
145+
def remove_suffix(content, version):
146+
if version + '.dev1' not in content:
147+
sys.stderr.write(
148+
"Version+Suffix {} not found, suffix may have already been "
149+
"removed.\n".format(version + '.dev1')
150+
)
151+
return False
152+
153+
content.replace(version + ' .dev1', version)
154+
return True
155+
156+
157+
if __name__ == "__main__":
158+
main()

0 commit comments

Comments
 (0)