Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add "standard" cogment release scripts #1

Merged
merged 8 commits into from
Jan 17, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
root = true

[*]
indent_style = space
indent_size = 2
charset = utf-8
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
max_line_length = 120

[{*.py,*.yml}]
indent_size = 4
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,4 @@ tutorial/*.html
.idea
vizdoom.ini

lib/
lib/
68 changes: 63 additions & 5 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,67 @@
stages:
- lint
- lint
- build
- publish

licenses_checker:
stage: lint
image: registry.gitlab.com/ai-r/cogment/license-checker:latest
script:
- license-checker
stage: lint
image: registry.gitlab.com/ai-r/cogment/license-checker:latest
script:
- license-checker

shellcheck:
image: koalaman/shellcheck-alpine:stable
stage: lint
before_script:
- shellcheck --version
script:
- shellcheck $(find . -name '*.sh' | xargs)

shfmt:
image: mvdan/shfmt:v3.1.0-alpine
stage: lint
before_script:
- shfmt -version
script:
- shfmt -i 2 -ci -d .

.base:
image: python:3.10
variables:
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
before_script:
- mkdir -p ${PIP_CACHE_DIR}
- python -m venv .venv
- source .venv/bin/activate
- pip install -r requirements.txt
- pip install -e .
cache:
- paths:
- .cache/pip
- key:
files:
- requirements.txt
- setup.cfg
paths:
- ".venv"

build_sdist:
extends: .base
stage: build
script:
- python -m build
- twine check dist/*
artifacts:
expire_in: 1 week
paths:
- dist/*.tar.gz
- dist/*.whl

publish_to_pypi:
extends: .base
stage: publish
script:
- python -m build
- python -m twine upload dist/* --non-interactive -u $PYPI_USERNAME -p $PYPI_PASSWORD
rules:
- if: $CI_COMMIT_TAG
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.1.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## Unreleased

### Added

- Initial release
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,21 @@ Terminology:
- Model: a relatively raw PyTorch (or other?) model, inheriting from `nn.Module`
- Agent: a model wrapped in some utility class to interact with np arrays
- Actor: a cogment service that may involve models and/or actors

## Release process

People having maintainers rights of the repository can follow these steps to release a version **MAJOR.MINOR.PATCH**. The versioning scheme follows [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

1. Run `./scripts/create_release_branch.sh MAJOR.MINOR.PATCH`, this will automatically:
- update the version of the package, in `cogment_lab/version.py`,
- create a release branch with this changes at `release/vMAJOR.MINOR.PATCH` and push it.
2. On the release branch:
- Make sure the changelog, at `CHANGELOG.md`, reflects the changes since the last release,
- Fix any issue, making sure that te build passes on CI,
- Commit and push any changes.
3. Run `./scripts/tag_release.sh MAJOR.MINOR.PATCH`, this will automatically:
- create the specific version section in the changelog and push it to the release branch,
- merge the release branch in `main`,
- create the release tag and,
- update the `develop` to match the latest release.
4. The CI will automatically publish the package to PyPI.
8 changes: 5 additions & 3 deletions cogment_lab/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,16 @@
# limitations under the License.

from __future__ import annotations

import logging

from cogment_lab.process_manager import Cogment
from cogment.utils import logger

logger.addHandler(logging.NullHandler())
from cogment_lab.process_manager import Cogment
from cogment_lab.version import __version__


__version__ = "0.0.1"
logger.addHandler(logging.NullHandler())


__all__ = ["Cogment"]
3 changes: 3 additions & 0 deletions cogment_lab/version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Copyright 2023 AI Redefined Inc. <[email protected]>

__version__ = "0.1.0"
77 changes: 77 additions & 0 deletions scripts/commons.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#!/usr/bin/env bash

####
# Helper functions & variables
####

ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
export ROOT_DIR

GIT_REMOTE="origin"
export GIT_REMOTE

# Let's check if we have GNU sed or BSD sed
if sed --help >/dev/null 2>&1; then
# There is a '--help' option, it is GNU BSD
SED_NL="\\n"
else
SED_NL="\\
"
fi
export SED_NL

# Generic functions

## join_by
## Examples:
## $ join_by "-delimiter-" "a" "b" "c"
## "a-delimiter-b-delimiter-c"
function join_by() {
local delimiter=$1
shift
local strings=$1
shift
printf %s "${strings}" "${@/#/$delimiter}"
}

## array_contains
## Examples:
## $ array_contains "foo" "bar" "foobaz"
## 1
##
## $ array_contains "foo" "bar" "foo" "baz"
## 0
function array_contains() {
local seeking=$1
shift
local array=("$@")
shift
for element in "${array[@]}"; do
if [[ "${element}" == "${seeking}" ]]; then
return 0
fi
done
return 1
}

# Version related functions

VERSION_SED_REGEX="[0-9]\{1,\}\.[0-9]\{1,\}\.[0-9]\{1,\}\(-[a-zA-Z0-9]\{1,\}\)\{0,1\}"

function validate_version() {
local input_version=$1
shift
local parsed_version
parsed_version=$(sed -n "s/^v\{0,1\}\(${VERSION_SED_REGEX}\)$/\1/p" <<<"${input_version}")
printf %s "${parsed_version}"
}

function retrieve_package_version() {
sed -n "s/^__version__[[:blank:]]*\=[[:blank:]]*\"\(${VERSION_SED_REGEX}\)\"/\1/p" "${ROOT_DIR}/cogment_lab/version.py"
}

function update_package_version() {
local version=$1
sed -i.bak "/^__version__[[:blank:]]*\=/s/${VERSION_SED_REGEX}/${version}/" "${ROOT_DIR}/cogment_lab/version.py"
retrieve_package_version
}
109 changes: 109 additions & 0 deletions scripts/create_release_branch.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#!/usr/bin/env bash

####
# Release preparation script
#
# Should be executed by the release manager to initiate the finalization work on a particular release
####

# shellcheck disable=SC1091
source "$(dirname "${BASH_SOURCE[0]}")/commons.sh"

function usage() {
local usage_str=""
usage_str+="Update the version and create a release branch\n\n"
usage_str+="Usage:\n"
usage_str+=" $(basename "${BASH_SOURCE[0]}") <version> [--dry-run]\n\n"
usage_str+=" version: looks like MAJOR.MINOR.PATCH[.PRERELEASE] having:\n"
usage_str+=" - MAJOR, MINOR and PATCH digit only,\n"
usage_str+=" - PRERELEASE optional, any string >1 alphanumerical characters.\n\n"
usage_str+="Options:\n"
usage_str+=" --dry-run: Do not push anything to the remote.\n"
usage_str+=" -h, --help: Show this screen.\n"
printf "%b" "${usage_str}"
}

set -o errexit

# Parse the command line arguments.
dry_run=0

while [[ "$1" != "" ]]; do
case $1 in
--dry-run)
dry_run=1
;;
--help | -h)
usage
exit 0
;;
*)
if [[ -z "${version}" ]]; then
input_version=$1
validated_version=$(validate_version "${input_version}")
if [[ -z "${validated_version}" ]]; then
printf "%s: provided version is invalid.\n\n" "${input_version}"
usage
exit 1
fi
version="${validated_version}"
else
printf "%s: unrecognized argument.\n\n" "$1"
usage
exit 1
fi
;;
esac
shift
done

if [[ -z "${version}" ]]; then
printf "Missing version.\n\n"
usage
exit 1
fi

printf "* Preparing release v%s...\n" "${version}"

# Move to the remote `develop` branch
git -C "${ROOT_DIR}" fetch -q "${GIT_REMOTE}"
git -C "${ROOT_DIR}" checkout -q "${GIT_REMOTE}/develop"

printf "** Now on the latest %s/develop\n" "${GIT_REMOTE}"

# Retrieving the current version of the package
current_version=$(retrieve_package_version)

printf "** Current version is v%s\n" "${current_version}"

# Creating the release branch, this will fail if the branch already exists
release_branch="release/v${version}"
git -C "${ROOT_DIR}" branch "${release_branch}"
git -C "${ROOT_DIR}" checkout -q "${release_branch}"

printf "** Release branch \"%s\" created\n" "${release_branch}"

# Updating the version of the package and commit
updated_version=$(update_package_version "${version}")
if [[ "${version}" != "${updated_version}" ]]; then
printf "Error while updating the version to %s.\n" "${version}"
exit 1
fi
git -C "${ROOT_DIR}" commit -q -a -m"Preparing release v${version}"

# TODO here we could ask / retrieve the latest version of the internal dependencies and update .cogment-api.yaml and .gitlab-ci.yml

printf "** Version updated to v%s\n" "${updated_version}"

if [[ "${dry_run}" == 1 ]]; then
printf "** DRY RUN SUCCESSFUL - Nothing pushed to %s\n" "${GIT_REMOTE}"
else
git -C "${ROOT_DIR}" push -q "${GIT_REMOTE}" "${release_branch}"
printf "** Release branch \"%s\" pushed to \"%s\" \n" "${release_branch}" "${GIT_REMOTE}"
fi

printf "* To finalize the release:\n"
printf "** Update the dependencies, in particular make sure nothing is relying on a \"latest\" version of another package.\n"
printf "** Check and update the package's changelog at \"%s/CHANGELOG.md\"\n" "${ROOT_DIR}"
printf "** Make sure the CI builds everything properly\n"
printf "** Finally, run \"%s %s\"\n" "$(dirname "${BASH_SOURCE[0]}")/tag_release.sh" "${version}"
Loading
Loading