Skip to content

Commit

Permalink
generate-metadata.SemanticVersion - update to include 'build' portion…
Browse files Browse the repository at this point in the history
… of semvar in container image tags using '_' instead of '+' since '+' isn't supported by container image tag syntax but not having the 'build' porition of the version on the tag can cause tags to unexpectadly get overwritten/lost if major.minor.patch isn't updated by applciation devs
  • Loading branch information
itewk committed Nov 11, 2021
1 parent e265481 commit 9e06701
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,30 +37,35 @@
* runtime configuration
* previous step results
Configuration Key | Required? | Default | Description
--------------------------------------|-----------|---------|-----------
`app-version` | Yes | | Value to use for `version` portion of semantic version (https://semver.org/). \
EX: `<app-version>`
`is-pre-release` | Yes | `False` | If `True` then will add any relevant `pre-release` identifiers to semantic version (https://semver.org/), \
such as the branch name. \
If `False` then assumed to be a release build and all `pre-release` identifiers will \
be ignored from version as per the semantic version spec (https://semver.org/).
`branch` | No | | If `is-pre-release` is `True`, value to use for a pre-release name in pre-release poriton of semantic version (https://semver.org/). \
EX: `<app-version>-<branch>`
`workflow-run-num` | No | | If `is-pre-release` is `True`, value to use for a numeric identifier of the branch `pre-release` identifier if provided. \
Also always used in build identifier. \
Since this can be included in the pre-release section, it should be incremental as per the sem version spec.
EX (pre-release): `<app-version>-<branch>.<workflow-run-num>+<sha>.<workflow-run-num>` <br/>\
EX (release): `<app-version>+<sha>.<workflow-run-num>`
`sha` | No | | Value to use for sha build identifier in build portion of semantic version. \
EX: `<app-version>+<sha>`
`sha-build-identifier-length` | No | 7 | Trim the given `sha` down to this length when including as build identifier in semantic version
`additional-pre-release-identifiers` | No | | If `is-pre-release` is `True`, additional `pre-release` identifiers to add to semantic version (https://semver.org/). \
Ignored if `is-pre-release` is `False. \
EX (pre-release): `<app-version>-<branch>.<workflow-run-num>-<additional-pre-release-identifiers>+<sha>.<workflow-run-num>`
`additional-build-identifiers` | No | | Additional `build` identifiers to add to semantic version (https://semver.org/). \
EX (pre-release): `<app-version>-<branch>.<workflow-run-num>+<sha>.<workflow-run-num>.<additional-build-identifiers>` <br/>\
EX (release): `<app-version>+<sha>.<workflow-run-num>.<additional-build-identifiers>`
Configuration Key | Required? | Default | Description
----------------------------------------|-----------|---------|-----------
`app-version` | Yes | | Value to use for `version` portion of semantic version (https://semver.org/). \
EX: `<app-version>`
`is-pre-release` | Yes | `False` | If `True` then will add any relevant `pre-release` identifiers to semantic version (https://semver.org/), \
such as the branch name. \
If `False` then assumed to be a release build and all `pre-release` identifiers will \
be ignored from version as per the semantic version spec (https://semver.org/).
`branch` | No | | If `is-pre-release` is `True`, value to use for a pre-release name in pre-release poriton of semantic version (https://semver.org/). \
EX: `<app-version>-<branch>`
`workflow-run-num` | No | | If `is-pre-release` is `True`, value to use for a numeric identifier of the branch `pre-release` identifier if provided. \
Also always used in build identifier. \
Since this can be included in the pre-release section, it should be incremental as per the sem version spec.
EX (pre-release): `<app-version>-<branch>.<workflow-run-num>+<sha>.<workflow-run-num>` <br/>\
EX (release): `<app-version>+<sha>.<workflow-run-num>`
`sha` | No | | Value to use for sha build identifier in build portion of semantic version. \
EX: `<app-version>+<sha>`
`sha-build-identifier-length` | No | 7 | Trim the given `sha` down to this length when including as build identifier in semantic version
`additional-pre-release-identifiers` | No | | If `is-pre-release` is `True`, additional `pre-release` identifiers to add to semantic version (https://semver.org/). \
Ignored if `is-pre-release` is `False. \
EX (pre-release): `<app-version>-<branch>.<workflow-run-num>-<additional-pre-release-identifiers>+<sha>.<workflow-run-num>`
`additional-build-identifiers` | No | | Additional `build` identifiers to add to semantic version (https://semver.org/). \
EX (pre-release): `<app-version>-<branch>.<workflow-run-num>+<sha>.<workflow-run-num>.<additional-build-identifiers>` <br/>\
EX (release): `<app-version>+<sha>.<workflow-run-num>.<additional-build-identifiers>`
`container-image-tag-build-deliminator` | Yes | `_` | Unfortunately the container image tag spec does not allow for the `+` character which means can not follow \
strict semver syntax when including the `build` portion of the semver in the image tag. \
The value here is used instead of the `+` for the purposes of container image tags. \
NOTE: the default `_` is chosen because it is otherwise not a valid character in semver syntax so if doing parsing \
against the standard semver spec/regex it is simple enough to swap the `+` for a `_` and still get accurate results.
Result Artifacts
----------------
Expand All @@ -82,12 +87,14 @@

DEFAULT_CONFIG = {
'is-pre-release': False,
'sha-build-identifier-length': 7
'sha-build-identifier-length': 7,
'container-image-tag-build-deliminator': '_'
}

REQUIRED_CONFIG_OR_PREVIOUS_STEP_RESULT_ARTIFACT_KEYS = [
'app-version',
'is-pre-release'
'is-pre-release',
'container-image-tag-build-deliminator'
]

class SemanticVersion(StepImplementer): # pylint: disable=too-few-public-methods
Expand Down Expand Up @@ -155,6 +162,7 @@ def _run_step(self):
build = self.__get_semantic_version_build()
if build:
version += f'+{build}'
image_tag += f"{self.get_value('container-image-tag-build-deliminator')}{build}"

# add artifacts
step_result.add_artifact(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,17 @@ def test_step_implementer_config_defaults(self):
defaults = SemanticVersion.step_implementer_config_defaults()
expected_defaults = {
'is-pre-release': False,
'sha-build-identifier-length': 7
'sha-build-identifier-length': 7,
'container-image-tag-build-deliminator': '_'
}
self.assertEqual(defaults, expected_defaults)

def test__required_config_or_result_keys(self):
required_keys = SemanticVersion._required_config_or_result_keys()
expected_required_keys = [
'app-version',
'is-pre-release'
'is-pre-release',
'container-image-tag-build-deliminator'
]
self.assertEqual(required_keys, expected_required_keys)

Expand Down Expand Up @@ -139,7 +141,7 @@ def test_app_version_and_build(self, mock_build, mock_pre_release):
)
expected_step_result.add_artifact(
name='container-image-tag',
value='0.42.1',
value='0.42.1_mock1',
description='Constructed semenatic version without build identifier' \
' since not compatible with container image tags'
)
Expand All @@ -160,7 +162,69 @@ def test_app_version_and_build(self, mock_build, mock_pre_release):
)
expected_step_result.add_evidence(
name='container-image-tag',
value='0.42.1_mock1',
description='semenatic version without build identifier' \
' since not compatible with container image tags'
)

self.assertEqual(actual_result, expected_step_result)
mock_pre_release.assert_not_called()
mock_build.assert_called_once()

def test_app_version_and_build_custom_container_image_tag_build_deliminator(self, mock_build, mock_pre_release):
# setup
step_config = {
'app-version': '0.42.1',
'container-image-tag-build-deliminator': '_-_'
}
step_implementer = self.create_step_implementer(
step_config=step_config,
step_name='generate-metadata',
implementer='SemanticVersion'
)

# setup mocks
mock_build.return_value = 'mock1'
mock_pre_release.return_value = None

# run test
actual_result= step_implementer._run_step()

# verify results
expected_step_result = StepResult(
step_name='generate-metadata',
sub_step_name='SemanticVersion',
sub_step_implementer_name='SemanticVersion'
)
expected_step_result.add_artifact(
name='version',
value='0.42.1+mock1',
description='Full constructured semantic version'
)
expected_step_result.add_artifact(
name='container-image-tag',
value='0.42.1_-_mock1',
description='Constructed semenatic version without build identifier' \
' since not compatible with container image tags'
)
expected_step_result.add_artifact(
name='semantic-version-core',
value='0.42.1',
description='Semantic version version core portion'
)
expected_step_result.add_artifact(
name='semantic-version-build',
value='mock1',
description='Semantic version build portion'
)
expected_step_result.add_evidence(
name='version',
value='0.42.1+mock1',
description='Full constructured semantic version'
)
expected_step_result.add_evidence(
name='container-image-tag',
value='0.42.1_-_mock1',
description='semenatic version without build identifier' \
' since not compatible with container image tags'
)
Expand Down Expand Up @@ -322,7 +386,7 @@ def test_app_version_and_is_pre_release_with_given_pre_release_identifiers_and_b
)
expected_step_result.add_artifact(
name='container-image-tag',
value='0.42.1-feature-mock1',
value='0.42.1-feature-mock1_mock3',
description='Constructed semenatic version without build identifier' \
' since not compatible with container image tags'
)
Expand All @@ -348,7 +412,7 @@ def test_app_version_and_is_pre_release_with_given_pre_release_identifiers_and_b
)
expected_step_result.add_evidence(
name='container-image-tag',
value='0.42.1-feature-mock1',
value='0.42.1-feature-mock1_mock3',
description='semenatic version without build identifier' \
' since not compatible with container image tags'
)
Expand Down

0 comments on commit 9e06701

Please sign in to comment.