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

Updates to PR#107 which was mostly done #110

Merged
merged 24 commits into from
Jun 28, 2022
Merged
Show file tree
Hide file tree
Changes from 23 commits
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
1 change: 1 addition & 0 deletions changelog.d/107.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add a `link_to_project` flag that will update the package project_urls in the setup.cfg with a link to the source code for the package.
15 changes: 8 additions & 7 deletions docs/Versioning.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,14 @@ The following settings are supported:

The setup.cfg go under the `screwdrivercd.verison` setting.

| Setting | Default Value | Description |
| ------------- | ------------------ | ----------------------------------------------------------------------- |
| version_type | git_revision_count | The versioning format to generate, choices: |
| | | git_revision_count - Update the last digit the number of git revisions |
| | | sdv4_sd_build - Update the last digit with the value of the SD_BUILD environment variable |
| | | utc_date - Generate a version based on the date, format: year.monthday.hourminutesecond |
| | | sdv4_date - Generate a version based on the date and SD_BUILD environment variable, format: year.month.SD_BUILD |
| Setting | Default Value | Description |
|-----------------|--------------------|-----------------------------------------------------------------------------------------------------------------|
| version_type | git_revision_count | The versioning format to generate, choices: |
| | | git_revision_count - Update the last digit the number of git revisions |
| | | sdv4_sd_build - Update the last digit with the value of the SD_BUILD environment variable |
| | | utc_date - Generate a version based on the date, format: year.monthday.hourminutesecond |
| | | sdv4_date - Generate a version based on the date and SD_BUILD environment variable, format: year.month.SD_BUILD |
| link_to_project | False | If set to True, a link to the source repo will be added to [metadata]project_urls in setup.cfg |

### Example

Expand Down
6 changes: 1 addition & 5 deletions screwdriver.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@ jobs:
- postinstall_dependencies: $BASE_PYTHON -m pip install -U .
requires: [~commit, ~pr]

validate_dependencies:
template: python/validate_dependencies
requires: [~commit, ~pr]

validate_lint:
template: python/validate_lint
requires: [~commit, ~pr]
Expand All @@ -51,7 +47,7 @@ jobs:
version:
template: python/generate_version
requires: [
validate_test, validate_lint, validate_codestyle, validate_dependencies, validate_security,
validate_test, validate_lint, validate_codestyle, validate_security,
dwighthubbard marked this conversation as resolved.
Show resolved Hide resolved
# validate_type
]

Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
author = Verizon Media Python Platform Team
author_email = python@verizonmedia.com
author_email = python@yahooinc.com
classifiers =
Development Status :: 5 - Production/Stable
Intended Audience :: Developers
Expand Down
2 changes: 1 addition & 1 deletion src/screwdrivercd/documentation/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,5 @@ def main(): # pragma: no cover
rc = 1
if is_pull_request():
status = 'SUCCESS' if rc == 0 else 'FAILURE'
update_job_status(status=status, message=f'{operation} {", ".join(documentation_formats)} documentation')
# update_job_status(status=status, message=f'{operation} {", ".join(documentation_formats)} documentation')
return rc
17 changes: 13 additions & 4 deletions src/screwdrivercd/version/arguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ def get_config_default(key, default=None, setup_cfg_filename='setup.cfg'):
return default


def get_bool_equivalent(key) -> bool:
""" Get the equivalent bool value for a string key in the config file. """

if isinstance(key, str) and key.lower() in ['false', '0', 'off']:
return False
return True


def parse_arguments():
"""
Parse the command line arguments
Expand All @@ -47,10 +55,10 @@ def parse_arguments():
"""
version_type = get_config_default('version_type', default='default')
update_meta = get_config_default('update_screwdriver_meta', default='false')
if isinstance(update_meta, str) and update_meta.lower() in ['false', '0', 'off']:
update_meta = False
else:
update_meta = True
update_meta = get_bool_equivalent(update_meta)
link_to_project = get_config_default('link_to_project', default='false')
link_to_project = get_bool_equivalent(link_to_project)

version_choices = list(versioners.keys())
if version_type not in version_choices:
raise VersionError(f'The version_type in the [screwdrivercd.version] section of setup.cfg has an invalid version type of {version_type!r}')
Expand All @@ -60,5 +68,6 @@ def parse_arguments():
parser.add_argument('--version_type', default=version_type, choices=version_choices, help='Type of version number to generate')
parser.add_argument('--ignore_meta', default=False, action='store_true', help='Ignore the screwdriver v4 metadata')
parser.add_argument('--update_meta', default=update_meta, action='store_true', help='Update the screwdriver v4 metadata with the new version')
parser.add_argument('--link_to_project', default=link_to_project, action='store_true', help='Add/update link to source project tree for current package version')
result = parser.parse_args()
return result
2 changes: 1 addition & 1 deletion src/screwdrivercd/version/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def main():
if args.force_update or setupcfg_has_metadata():
versioner = versioners[args.version_type]
print(f'Updating version using the {versioner.name} version plugin', flush=True)
version = versioner(ignore_meta_version=args.ignore_meta, update_sdv4_meta=args.update_meta)
version = versioner(ignore_meta_version=args.ignore_meta, update_sdv4_meta=args.update_meta, link_to_project=args.link_to_project)

version.update_setup_cfg_metadata()
if args.update_meta:
Expand Down
45 changes: 41 additions & 4 deletions src/screwdrivercd/version/version_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
LOG = logging.getLogger(__name__)


class Version():
class Version:
"""
Base Screwdriver Versioning class
"""
Expand All @@ -22,12 +22,13 @@ class Version():
setup_cfg_filename: str = 'setup.cfg'
_meta_version: str = ''

def __init__(self, setup_cfg_filename=None, ignore_meta_version: bool=False, update_sdv4_meta: bool=True, meta_command: str='meta'):
def __init__(self, setup_cfg_filename=None, ignore_meta_version: bool = False, update_sdv4_meta: bool = True, meta_command: str = 'meta', link_to_project: bool = False):
if setup_cfg_filename: # pragma: no cover
self.setup_cfg_filename = setup_cfg_filename
self.meta_command = meta_command
self.ignore_meta_version = ignore_meta_version
self.update_sdv4_meta = update_sdv4_meta
self.link_to_project = link_to_project

def __repr__(self):
return repr(self.version)
Expand Down Expand Up @@ -67,18 +68,53 @@ def generate(self):
"""
return self.read_setup_version()

def get_link_to_project_using_hash(self):
"""
Generate and return link to build-triggering commit using its SHA hash
"""
scm_url = os.environ.get('SCM_URL', '')
sha = os.environ.get('SD_BUILD_SHA', '')
if self.link_to_project and scm_url and sha:
if scm_url.startswith('git@'):
hostname = scm_url.split(':')[0].split('@')[1]
path = ':'.join(scm_url.split(':')[1:])
return f'https://{hostname}/{path}/tree/{sha}'
else:
return f'{scm_url}/tree/{sha}'
return ''

def update_setup_cfg_metadata(self):
"""
Update the version value in the setup.cfg file
"""
if not self.version: # pragma: no cover
return
link_to_project = self.get_link_to_project_using_hash()
config = configparser.ConfigParser()
config.read(self.setup_cfg_filename)
if 'metadata' not in config.sections():
config['metadata'] = {}

config['metadata']['version'] = self.version
if link_to_project:
project_urls_str = config['metadata'].get('project_urls', '')
project_urls_dict = {}
if project_urls_str:
for entry in project_urls_str.split(os.linesep):
entry = entry.strip()
if '=' in entry:
key, value = entry.split('=')
key = key.strip()
value = value.strip()
project_urls_dict[key] = value

project_urls_dict['Source'] = link_to_project

project_urls_str = '\n'
for key, value in project_urls_dict.items():
project_urls_str += f'{key} = {value}\n'

config['metadata']['project_urls'] = project_urls_str.rstrip('\n')

with open(self.setup_cfg_filename, 'w') as config_file_handle:
config.write(config_file_handle)
Expand Down Expand Up @@ -187,7 +223,7 @@ def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

def revision_value(self): # pragma: no cover
"Method to return a newly generatated revision value"
"""Method to return a newly generated revision value"""
return self.default_revision_value

def generate(self): # pragma: no cover
Expand Down Expand Up @@ -245,6 +281,7 @@ class VersionSDV4Build(VersionUpdateRevision):
Each new screwdriver job run will increment the revision number.
"""
name = 'sdv4_SD_BUILD'

def revision_value(self):
revision = os.environ.get('SD_BUILD', None)
if not revision:
Expand Down Expand Up @@ -305,6 +342,6 @@ def generate(self):
}

# Make sure the versioners are listed all lowercase to make identifying them easier
for key, value in list(versioners.items()):
for key, value in list(versioners.items()):
if key.lower() not in versioners.keys():
versioners[key.lower()] = value
1 change: 0 additions & 1 deletion tests/test_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import sys

from json import dumps
from unittest import skip

from screwdrivercd.packaging.build_python import build_sdist_package, build_wheel_packages
from screwdrivercd.utility.environment import standard_directories
Expand Down
77 changes: 76 additions & 1 deletion tests/test_versioners.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,90 @@
from screwdrivercd.version.version_types import versioners, Version, VersionGitRevisionCount, VersionSDV4Build, VersionDateSDV4Build, VersionUTCDate, VersionManualUpdate


existing_project_url_config = {
'setup.cfg': b"""
[metadata]
author = Yahoo Python Platform Team
author_email = python@verizonmedia.com
name=mypyvalidator
project_urls =
Documentation = https://yahoo.github.io/mypyvalidator/
Change Log = https://yahoo.github.io/python-screwdrivercd/changelog/
CI Pipeline = https://cd.screwdriver.cd/pipelines/1
Source = https://github.com/yahoo/mypyvalidator/tree/a5c3785ed8d6a35868bc169f07e40e889087fd2e
version=0.0.0

[options]
packages =
mypyvalidator

package_dir =
=src
"""
}


class TestVersioners(ScrewdriverTestCase):
environ_keys = {
'BASE_PYTHON', 'PACKAGE_DIR', 'PACKAGE_DIRECTORY', 'SD_ARTIFACTS_DIR', 'SD_BUILD', 'SD_BUILD_ID',
'SD_PULL_REQUEST',
'SD_PULL_REQUEST', 'SCM_URL', 'SD_BUILD_SHA',
}

def test__version__read_setup_version__no_version(self):
version = Version(ignore_meta_version=True).read_setup_version()
self.assertEqual(version, Version.default_version)

def test__version__get_link_to_project_using_hash__unset_env_variables(self):
link = Version(ignore_meta_version=True, link_to_project=True).get_link_to_project_using_hash()
self.assertEqual(link, '')

def test__version__get_link_to_project_using_hash__set_and_unset_env_variables(self):
os.environ['SD_BUILD_SHA'] = 'a5c3785ed8d6a35868bc169f07e40e889087fd2e'
link = Version(ignore_meta_version=True, link_to_project=True).get_link_to_project_using_hash()
self.assertEqual(link, '')

def test__version__get_link_to_project_using_hash__set_env_variables__https_git(self):
os.environ['SCM_URL'] = 'https://github.com/org/project'
os.environ['SD_BUILD_SHA'] = 'a5c3785ed8d6a35868bc169f07e40e889087fd2e'
ver = Version(ignore_meta_version=True, link_to_project=True)
link = ver.get_link_to_project_using_hash()
self.assertEqual(link, 'https://github.com/org/project/tree/a5c3785ed8d6a35868bc169f07e40e889087fd2e')

ver.update_setup_cfg_metadata()
self.assertTrue(os.path.exists('setup.cfg'))
with open('setup.cfg') as fh:
setup_cfg = fh.read()
self.assertIn(link, setup_cfg)

def test__version__get_link_to_project_using_hash__set_env_variables__https_git__existing_project_urls(self):
os.environ['SCM_URL'] = 'https://github.com/org/project'
os.environ['SD_BUILD_SHA'] = 'a5c3785ed8d6a35868bc169f07e40e889087fd2e'
self.write_config_files(existing_project_url_config)

ver = Version(ignore_meta_version=True, link_to_project=True)
link = ver.get_link_to_project_using_hash()
self.assertEqual(link, 'https://github.com/org/project/tree/a5c3785ed8d6a35868bc169f07e40e889087fd2e')

ver.update_setup_cfg_metadata()
self.assertTrue(os.path.exists('setup.cfg'))
with open('setup.cfg') as fh:
setup_cfg = fh.read()
self.assertIn(link, setup_cfg)
self.assertIn('Documentation = https://yahoo.github.io/mypyvalidator/', setup_cfg)

def test__version__get_link_to_project_using_hash__set_env_variables__ssh_git(self):
os.environ['SCM_URL'] = 'git@github.com:org/project'
os.environ['SD_BUILD_SHA'] = 'a5c3785ed8d6a35868bc169f07e40e889087fd2e'
ver = Version(ignore_meta_version=True, link_to_project=True)
link = ver.get_link_to_project_using_hash()
self.assertEqual(link, 'https://github.com/org/project/tree/a5c3785ed8d6a35868bc169f07e40e889087fd2e')

ver.update_setup_cfg_metadata()
self.assertTrue(os.path.exists('setup.cfg'))
with open('setup.cfg') as fh:
setup_cfg = fh.read()
self.assertIn(link, setup_cfg)

def test__manual_version_update(self):
with NamedTemporaryFile('w') as file:
setup_cfg_content = '[metadata]\nversion = 1.0.5'
Expand Down Expand Up @@ -77,6 +151,7 @@ def test__sdv4_SD_BUILD__set(self):

def test__sdv4_SD_BUILD__PR__unset(self):
self.delkeys(['SD_BUILD', 'SD_BUILD_ID', 'SD_PULL_REQUEST'])
os.environ['SD_PULL_REQUEST'] = '1'
with self.assertRaises(VersionError):
version = str(VersionSDV4Build(ignore_meta_version=True, log_errors=False))

Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package_dir = src/screwdrivercd
package_name = screwdrivercd

[tox]
envlist = py36,py37,py38,py39
envlist = py37,py38,py39,py310
skip_missing_interpreters = true

[testenv]
Expand Down