def calculate_base_branch(version, path): """ The branch a release branch is created from depends on the release type and sometimes which pre-releases have preceeded this. :param bytes version: The version of Flocker to get a base branch for. :param bytes path: See :func:`git.Repo.init`. :returns: The base branch from which the new release branch was created. """ if not (is_release(version) or is_weekly_release(version) or is_pre_release(version)): raise NotARelease() repo = Repo(path=path, search_parent_directories=True) existing_tags = [tag for tag in repo.tags if tag.name == version] if existing_tags: raise TagExists() # We always base releases off master now. base_branch_name = 'master' # We create a new branch from a branch, not a tag, because a maintenance # or documentation change may have been applied to the branch and not the # tag. # The branch must be available locally for the next step. repo.git.checkout(base_branch_name) return (branch for branch in repo.branches if branch.name == base_branch_name).next()
def calculate_base_branch(version, path): """ The branch a release branch is created from depends on the release type and sometimes which pre-releases have preceeded this. :param bytes version: The version of Flocker to get a base branch for. :param bytes path: See :func:`git.Repo.init`. :returns: The base branch from which the new release branch was created. """ if not (is_release(version) or is_weekly_release(version) or is_pre_release(version)): raise NotARelease() repo = Repo(path=path, search_parent_directories=True) existing_tags = [tag for tag in repo.tags if tag.name == version] if existing_tags: raise TagExists() # We always base releases off master now. base_branch_name = 'master' # We create a new branch from a branch, not a tag, because a maintenance # or documentation change may have been applied to the branch and not the # tag. # The branch must be available locally for the next step. repo.git.checkout(base_branch_name) return ( branch for branch in repo.branches if branch.name == base_branch_name).next()
def parseArgs(self): version = self['flocker-version'] if not (is_release(version) or is_weekly_release(version) or is_pre_release(version)): raise NotARelease() if get_doc_version(version) != version: raise DocumentationRelease()
def upload_rpms(scratch_directory, target_bucket, version, build_server): """ Upload RPMS from build server to yum repository. :param FilePath scratch_directory: Temporary directory to download repository to. :param bytes target_bucket: S3 bucket to upload repository to. :param bytes version: Version to download RPMs for. :param bytes build_server: Server to download new RPMs from. """ if not (is_release(version) or is_weekly_release(version) or is_pre_release(version)): raise NotARelease() if get_doc_version(version) != version: raise DocumentationRelease() is_dev = not is_release(version) if is_dev: target_distro_suffix = "-testing" else: target_distro_suffix = "" operating_systems = [ {'distro': 'fedora', 'version': '20', 'arch': 'x86_64'}, {'distro': 'centos', 'version': '7', 'arch': 'x86_64'}, ] for operating_system in operating_systems: yield update_repo( rpm_directory=scratch_directory.child( b'{}-{}-{}'.format( operating_system['distro'], operating_system['version'], operating_system['arch'])), target_bucket=target_bucket, target_key=os.path.join( operating_system['distro'] + target_distro_suffix, operating_system['version'], operating_system['arch']), source_repo=os.path.join( build_server, b'results/omnibus', version, b'{}-{}'.format( operating_system['distro'], operating_system['version'])), packages=FLOCKER_PACKAGES, flocker_version=version, distro_name=operating_system['distro'], distro_version=operating_system['version'], )
def publish_docs(flocker_version, doc_version, environment): """ Publish the Flocker documentation. The documentation for each version of Flocker is uploaded to a development bucket on S3 by the build server and this copies the documentation for a particular ``flocker_version`` and publishes it as ``doc_version``. Attempting to publish documentation to a staging environment as a documentation version publishes it as the version being updated. :param bytes flocker_version: The version of Flocker to publish the documentation for. :param bytes doc_version: The version to publish the documentation as. :param Environments environment: The environment to publish the documentation to. :raises NotARelease: Raised if trying to publish to a version that isn't a release. :raises NotTagged: Raised if publishing to production and the version being published version isn't tagged. """ if not (is_release(doc_version) or is_weekly_release(doc_version) or is_pre_release(doc_version)): raise NotARelease() if environment == Environments.PRODUCTION: if get_doc_version(flocker_version) != doc_version: raise NotTagged() configuration = DOCUMENTATION_CONFIGURATIONS[environment] dev_prefix = '%s/' % (flocker_version,) version_prefix = 'en/%s/' % (get_doc_version(doc_version),) is_dev = not is_release(doc_version) if is_dev: stable_prefix = "en/devel/" else: stable_prefix = "en/latest/" # Get the list of keys in the new documentation. new_version_keys = yield Effect( ListS3Keys(bucket=configuration.dev_bucket, prefix=dev_prefix)) # Get the list of keys already existing for the given version. # This should only be non-empty for documentation releases. existing_version_keys = yield Effect( ListS3Keys(bucket=configuration.documentation_bucket, prefix=version_prefix)) # Copy the new documentation to the documentation bucket. yield Effect( CopyS3Keys(source_bucket=configuration.dev_bucket, source_prefix=dev_prefix, destination_bucket=configuration.documentation_bucket, destination_prefix=version_prefix, keys=new_version_keys)) # Delete any keys that aren't in the new documentation. yield Effect( DeleteS3Keys(bucket=configuration.documentation_bucket, prefix=version_prefix, keys=existing_version_keys - new_version_keys)) # Update the key used for error pages if we're publishing to staging or if # we're publishing a marketing release to production. if ((environment is Environments.STAGING) or (environment is Environments.PRODUCTION and not is_dev)): yield Effect( UpdateS3ErrorPage(bucket=configuration.documentation_bucket, target_prefix=version_prefix)) # Update the redirect for the stable URL (en/latest/ or en/devel/) # to point to the new version. Returns the old target. old_prefix = yield Effect( UpdateS3RoutingRule(bucket=configuration.documentation_bucket, prefix=stable_prefix, target_prefix=version_prefix)) # If we have changed versions, get all the keys from the old version if old_prefix: previous_version_keys = yield Effect( ListS3Keys(bucket=configuration.documentation_bucket, prefix=old_prefix)) else: previous_version_keys = set() # The changed keys are the new keys, the keys that were deleted from this # version, and the keys for the previous version. changed_keys = (new_version_keys | existing_version_keys | previous_version_keys) # S3 serves /index.html when given /, so any changed /index.html means # that / changed as well. # Note that we check for '/index.html' but remove 'index.html' changed_keys |= {key_name[:-len('index.html')] for key_name in changed_keys if key_name.endswith('/index.html')} # Always update the root. changed_keys |= {''} # The full paths are all the changed keys under the stable prefix, and # the new version prefix. This set is slightly bigger than necessary. changed_paths = {prefix + key_name for key_name in changed_keys for prefix in [stable_prefix, version_prefix]} # Invalidate all the changed paths in cloudfront. yield Effect( CreateCloudFrontInvalidation(cname=configuration.cloudfront_cname, paths=changed_paths))
def publish_docs(flocker_version, doc_version, environment): """ Publish the Flocker documentation. The documentation for each version of Flocker is uploaded to a development bucket on S3 by the build server and this copies the documentation for a particular ``flocker_version`` and publishes it as ``doc_version``. Attempting to publish documentation to a staging environment as a documentation version publishes it as the version being updated. :param bytes flocker_version: The version of Flocker to publish the documentation for. :param bytes doc_version: The version to publish the documentation as. :param Environments environment: The environment to publish the documentation to. :raises NotARelease: Raised if trying to publish to a version that isn't a release. :raises NotTagged: Raised if publishing to production and the version being published version isn't tagged. """ if not (is_release(doc_version) or is_weekly_release(doc_version) or is_pre_release(doc_version)): raise NotARelease() if environment == Environments.PRODUCTION: if get_doc_version(flocker_version) != doc_version: raise NotTagged() configuration = DOCUMENTATION_CONFIGURATIONS[environment] dev_prefix = '%s/' % (flocker_version, ) version_prefix = 'en/%s/' % (get_doc_version(doc_version), ) is_dev = not is_release(doc_version) if is_dev: stable_prefix = "en/devel/" else: stable_prefix = "en/latest/" # Get the list of keys in the new documentation. new_version_keys = yield Effect( ListS3Keys(bucket=configuration.dev_bucket, prefix=dev_prefix)) # Get the list of keys already existing for the given version. # This should only be non-empty for documentation releases. existing_version_keys = yield Effect( ListS3Keys(bucket=configuration.documentation_bucket, prefix=version_prefix)) # Copy the new documentation to the documentation bucket. yield Effect( CopyS3Keys(source_bucket=configuration.dev_bucket, source_prefix=dev_prefix, destination_bucket=configuration.documentation_bucket, destination_prefix=version_prefix, keys=new_version_keys)) # Delete any keys that aren't in the new documentation. yield Effect( DeleteS3Keys(bucket=configuration.documentation_bucket, prefix=version_prefix, keys=existing_version_keys - new_version_keys)) # Update the key used for error pages if we're publishing to staging or if # we're publishing a marketing release to production. if ((environment is Environments.STAGING) or (environment is Environments.PRODUCTION and not is_dev)): yield Effect( UpdateS3ErrorPage(bucket=configuration.documentation_bucket, target_prefix=version_prefix)) # Update the redirect for the stable URL (en/latest/ or en/devel/) # to point to the new version. Returns the old target. old_prefix = yield Effect( UpdateS3RoutingRule(bucket=configuration.documentation_bucket, prefix=stable_prefix, target_prefix=version_prefix)) # If we have changed versions, get all the keys from the old version if old_prefix: previous_version_keys = yield Effect( ListS3Keys(bucket=configuration.documentation_bucket, prefix=old_prefix)) else: previous_version_keys = set() # The changed keys are the new keys, the keys that were deleted from this # version, and the keys for the previous version. changed_keys = (new_version_keys | existing_version_keys | previous_version_keys) # S3 serves /index.html when given /, so any changed /index.html means # that / changed as well. # Note that we check for '/index.html' but remove 'index.html' changed_keys |= { key_name[:-len('index.html')] for key_name in changed_keys if key_name.endswith('/index.html') } # Always update the root. changed_keys |= {''} # The full paths are all the changed keys under the stable prefix, and # the new version prefix. This set is slightly bigger than necessary. changed_paths = { prefix + key_name for key_name in changed_keys for prefix in [stable_prefix, version_prefix] } # Invalidate all the changed paths in cloudfront. yield Effect( CreateCloudFrontInvalidation(cname=configuration.cloudfront_cname, paths=changed_paths))
def calculate_base_branch(version, path): """ The branch a release branch is created from depends on the release type and sometimes which pre-releases have preceeded this. :param bytes version: The version of Flocker to get a base branch for. :param bytes path: See :func:`git.Repo.init`. :returns: The base branch from which the new release branch was created. """ if not (is_release(version) or is_weekly_release(version) or is_pre_release(version)): raise NotARelease() repo = Repo(path=path, search_parent_directories=True) existing_tags = [tag for tag in repo.tags if tag.name == version] if existing_tags: raise TagExists() release_branch_prefix = 'release/flocker-' if is_weekly_release(version): base_branch_name = 'master' elif is_pre_release(version) and get_pre_release(version) == 1: base_branch_name = 'master' elif get_doc_version(version) != version: base_branch_name = release_branch_prefix + get_doc_version(version) else: if is_pre_release(version): target_version = target_release(version) else: target_version = version pre_releases = [] for tag in repo.tags: try: if (is_pre_release(tag.name) and target_version == target_release(tag.name)): pre_releases.append(tag.name) except UnparseableVersion: # The Flocker repository contains versions which are not # currently considered valid versions. pass if not pre_releases: raise NoPreRelease() latest_pre_release = sorted( pre_releases, key=lambda pre_release: get_pre_release(pre_release))[-1] if (is_pre_release(version) and get_pre_release(version) > get_pre_release(latest_pre_release) + 1): raise MissingPreRelease() base_branch_name = release_branch_prefix + latest_pre_release # We create a new branch from a branch, not a tag, because a maintenance # or documentation change may have been applied to the branch and not the # tag. # The branch must be available locally for the next step. repo.git.checkout(base_branch_name) return ( branch for branch in repo.branches if branch.name == base_branch_name).next()
def calculate_base_branch(version, path): """ The branch a release branch is created from depends on the release type and sometimes which pre-releases have preceeded this. :param bytes version: The version of Flocker to get a base branch for. :param bytes path: See :func:`git.Repo.init`. :returns: The base branch from which the new release branch was created. """ if not (is_release(version) or is_weekly_release(version) or is_pre_release(version)): raise NotARelease() repo = Repo(path=path, search_parent_directories=True) existing_tags = [tag for tag in repo.tags if tag.name == version] if existing_tags: raise TagExists() release_branch_prefix = 'release/flocker-' if is_weekly_release(version): base_branch_name = 'master' elif is_pre_release(version) and get_pre_release(version) == 1: base_branch_name = 'master' elif get_doc_version(version) != version: base_branch_name = release_branch_prefix + get_doc_version(version) else: if is_pre_release(version): target_version = target_release(version) else: target_version = version pre_releases = [] for tag in repo.tags: try: if (is_pre_release(tag.name) and target_version == target_release(tag.name)): pre_releases.append(tag.name) except UnparseableVersion: # The Flocker repository contains versions which are not # currently considered valid versions. pass if not pre_releases: raise NoPreRelease() latest_pre_release = sorted( pre_releases, key=lambda pre_release: get_pre_release(pre_release))[-1] if (is_pre_release(version) and get_pre_release(version) > get_pre_release(latest_pre_release) + 1): raise MissingPreRelease() base_branch_name = release_branch_prefix + latest_pre_release # We create a new branch from a branch, not a tag, because a maintenance # or documentation change may have been applied to the branch and not the # tag. # The branch must be available locally for the next step. repo.git.checkout(base_branch_name) return (branch for branch in repo.branches if branch.name == base_branch_name).next()