Skip to content

Commit 7a68e5a

Browse files
finer-grained-cicd
Summary: - Tag parse log inside this repository. - Tags reflective of registry current health.
1 parent 278e8e4 commit 7a68e5a

File tree

3 files changed

+196
-8
lines changed

3 files changed

+196
-8
lines changed

.github/workflows/scenario.yaml

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,25 @@ jobs:
2121
run: |
2222
sudo apt-get update
2323
sudo apt-get install -y jq
24+
25+
- name: Setup Python
26+
uses: actions/[email protected]
27+
with:
28+
cache: pip
29+
python-version: '3.11'
30+
31+
- name: Install Python dependencies
32+
run: |
33+
pip3 install -r cicd/requirements.txt
2434
2535
- name: Ref Parse
2636
run: |
2737
_defaultRunType="${{ env.RUNTYPE_READ_ONLY }}"
28-
runID="$(echo -n '${{ github.ref_name }}' | cut -d '-' -f 2)"
29-
runType="$(echo -n '${{ github.ref_name }}' | cut -d '-' -f 3)"
30-
repositoryShorthand="$(echo -n '${{ github.ref_name }}' | rev | cut -d '-' -f 1 | rev)"
38+
tag_obj="$(python3 cicd/python/tag_parse.py '${{ github.ref_name }}' --parse-scenario-tag)"
39+
echo "tag_obj: $tag_obj"
40+
runID="$(echo "${tag_obj}" | jq -r '.run_id')"
41+
runType="$(echo "${tag_obj}" | jq -r '.run_type')"
42+
repositoryShorthand="$(echo "${tag_obj}" | jq -r '.repository_shorthand')"
3143
artifactRepositoryFullName='stackql/stackql'
3244
if [ "$repositoryShorthand" = "devel" ]; then
3345
artifactRepositoryFullName='stackql/stackql-devel'
@@ -81,10 +93,6 @@ jobs:
8193
GCP_RO_SECRET: ${{ secrets.CI_SCENARIO_GCP_RO_SECRET }}
8294
GCP_RW_SECRET: ${{ secrets.CI_SCENARIO_GCP_RW_SECRET }}
8395

84-
- name: Install Python dependencies
85-
run: |
86-
pip3 install -r cicd/requirements.txt
87-
8896
- name: Run Read Only Walkthrough Scenarios
8997
if: ${{ env.runType == env.RUNTYPE_READ_ONLY || env.runType == env.RUNTYPE_ALL }}
9098
env:

cicd/python/tag_parse.py

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
2+
import argparse
3+
import json
4+
import re
5+
6+
from typing import List, Optional
7+
8+
class _Tag(object):
9+
10+
def __init__(
11+
self,
12+
raw_tag: str,
13+
is_integration: bool = False,
14+
is_release: bool = False,
15+
is_hotfix: bool = False,
16+
is_prerelease: bool = False,
17+
is_build: bool = False,
18+
is_invalid: bool = False,
19+
is_regression: bool = False,
20+
is_robot: bool = False,
21+
repository_shorthand: Optional[str] = None,
22+
run_type: Optional[str] = None,
23+
run_id: Optional[str] = None,
24+
):
25+
self._raw_tag = raw_tag
26+
self._is_integration = is_integration
27+
self._is_release = is_release
28+
self._is_hotfix = is_hotfix
29+
self._is_prerelease = is_prerelease
30+
self._is_build = is_build
31+
self._is_invalid = is_invalid
32+
self._is_regression = is_regression
33+
self._is_robot = is_robot
34+
self._repository_shorthand = repository_shorthand if repository_shorthand else ''
35+
self._run_type = run_type if run_type else ''
36+
self._run_id = run_id if run_id else ''
37+
38+
39+
def is_robot(self) -> bool:
40+
return self._is_robot
41+
42+
def is_regression(self) -> bool:
43+
return self._is_regression
44+
45+
def get_run_id(self) -> str:
46+
return self._run_id
47+
48+
def get_run_type(self) -> str:
49+
return self._run_type
50+
51+
def get_repository_shorthand(self) -> str:
52+
return self._repository_shorthand
53+
54+
def _to_dict(self) -> dict:
55+
return {
56+
'raw_tag': self._raw_tag,
57+
'is_integration': self._is_integration,
58+
'is_release': self._is_release,
59+
'is_hotfix': self._is_hotfix,
60+
'is_prerelease': self._is_prerelease,
61+
'is_build': self._is_build,
62+
'is_invalid': self._is_invalid,
63+
'is_regression': self._is_regression,
64+
'is_robot': self._is_robot,
65+
'repository_shorthand': self.get_repository_shorthand(),
66+
'run_type': self._run_type,
67+
'run_id': self._run_id,
68+
}
69+
70+
def json(self) -> str:
71+
return json.dumps(self._to_dict())
72+
73+
74+
class _TagParser(object):
75+
76+
_BUILD_ONLY_TAG_PATTERN = re.compile(r'^build-(?P<descriptor>[^-]*)-(?P<seq>\d+).*$')
77+
_BUILD_RELEASE_TAG_PATTERN = re.compile(r'^build-release-(?P<descriptor>[^-]*)-(?P<seq>\d+).*$')
78+
_SCENARIO_ONLY_TAG_PATTERN = re.compile(r'^scenario-(?P<run_id>[^-]*)-(?P<run_type>[^-]*)-(?P<repository_shorthand>[^-]*)$')
79+
_ROBOT_TAG_PATTERN = re.compile(r'^robot-(?P<run_id>[^-]*)-(?P<run_type>[^-]*)-(?P<repository_shorthand>[^-]*)-(?P<seq>\d+)$')
80+
_ROBOT_ONLY_TAG_PATTERN = re.compile(r'^robot-(?P<descriptor>[^-]*)-(?P<seq>\d+).*$')
81+
_REGRESSION_ONLY_TAG_PATTERN = re.compile(r'^regression-(?P<descriptor>[^-]*)-(?P<seq>\d+).*$')
82+
83+
def __init__(
84+
self,
85+
raw_tag: str,
86+
permitted_types: List[str]
87+
):
88+
self._raw_tag = raw_tag
89+
self._permitted_types = permitted_types
90+
91+
def _parse_build_tag(self) -> _Tag:
92+
match = self._BUILD_ONLY_TAG_PATTERN.match(self._raw_tag)
93+
if match:
94+
return _Tag(raw_tag=self._raw_tag, is_build=True)
95+
match = self._BUILD_RELEASE_TAG_PATTERN.match(self._raw_tag)
96+
if match:
97+
return _Tag(raw_tag=self._raw_tag, is_build=True)
98+
return None
99+
100+
def _parse_scenario_tag(self) -> _Tag:
101+
match = self._SCENARIO_ONLY_TAG_PATTERN.match(self._raw_tag)
102+
run_id = match.group('run_id')
103+
run_type = match.group('run_type')
104+
repository_shorthand = match.group('repository_shorthand')
105+
if run_id and run_type:
106+
return _Tag(raw_tag=self._raw_tag, is_integration=True, run_id=run_id, run_type=run_type, repository_shorthand=repository_shorthand)
107+
return None
108+
109+
def _parse_robot_tag(self) -> _Tag:
110+
match = self._ROBOT_TAG_PATTERN.match(self._raw_tag)
111+
if match:
112+
return _Tag(raw_tag=self._raw_tag, is_robot=True)
113+
match = self._ROBOT_ONLY_TAG_PATTERN.match(self._raw_tag)
114+
if match:
115+
return _Tag(raw_tag=self._raw_tag, is_robot=True)
116+
return None
117+
118+
def _parse_regression_tag(self) -> _Tag:
119+
match = self._REGRESSION_ONLY_TAG_PATTERN.match(self._raw_tag)
120+
if match:
121+
return _Tag(raw_tag=self._raw_tag, is_regression=True)
122+
return None
123+
124+
def parse(self) -> _Tag:
125+
if not self._permitted_types:
126+
raise ValueError('No permitted types specified')
127+
for t in self._permitted_types:
128+
if t == 'build':
129+
tag = self._parse_build_tag()
130+
if tag:
131+
return tag
132+
elif t == 'scenario':
133+
tag = self._parse_scenario_tag()
134+
if tag:
135+
return tag
136+
elif t == 'robot':
137+
tag = self._parse_robot_tag()
138+
if tag:
139+
return tag
140+
elif t == 'regression':
141+
tag = self._parse_regression_tag()
142+
if tag:
143+
return tag
144+
raise ValueError(f'Raw tag: "{self._raw_tag}" is incompatible with permitted types: {" ".join(self._permitted_types)}')
145+
146+
def _parse_args() -> argparse.Namespace:
147+
"""
148+
Parse the arguments.
149+
"""
150+
parser = argparse.ArgumentParser(description='Handle and interpret git tags.')
151+
parser.add_argument('tag', help='The tag to parse', type=str)
152+
parser.add_argument('--parse-registry-tag', help='Opt-in to parse a registry tag', action=argparse.BooleanOptionalAction)
153+
parser.add_argument('--parse-scenario-tag', help='Opt-in to parse a scenario tag', action=argparse.BooleanOptionalAction)
154+
return parser.parse_args()
155+
156+
def main():
157+
args = _parse_args()
158+
if args.parse_registry_tag:
159+
tag_parser = _TagParser(args.tag, ['robot', 'regression'])
160+
tag = tag_parser.parse()
161+
if tag.is_robot():
162+
print(tag.json())
163+
return
164+
elif tag.is_regression():
165+
print(tag.json())
166+
return
167+
if args.parse_scenario_tag:
168+
tag_parser = _TagParser(args.tag, ['scenario'])
169+
tag = tag_parser.parse()
170+
if tag.get_run_id() and tag.get_run_type():
171+
print(tag.json())
172+
return
173+
else:
174+
raise ValueError(f'Invalid scenario tag inferred: {tag.json()}')
175+
raise ValueError('No action specified')
176+
177+
if __name__ == '__main__':
178+
main()
179+

test/robot/functional/stackql_mocked_from_cmd_line.robot

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7283,6 +7283,7 @@ Show Methods Path Level Parameters Considered as Exemplified by Azure Dev Center
72837283
... stderr=${CURDIR}/tmp/Show-Methods-Path-Level-Parameters-Considered-as-Exemplified-by-Azure-Dev-Center-Customization-Tasks-Methods-stderr.tmp
72847284

72857285
Set Statement Update Auth Scenario Working
7286+
[Tags] registry tls_proxied
72867287
${inputStr} = Catenate
72877288
... set session "$.auth.google.credentialsfilepath"='${AUTH_GOOGLE_SA_KEY_PATH}';
72887289
... select name, id, network, split_part(network, '/', 8) as network_region from google.compute.firewalls where project \= 'testing-project' order by id desc;
@@ -7396,7 +7397,7 @@ Alternate App Root Persists All Temp Materials in Alotted Directory
73967397
Directory Should Exist ${TEST_TMP_EXEC_APP_ROOT_NATIVE}${/}src
73977398

73987399
View Tuple Replacement Working As Exemplified by AWS EC2 Instances List and Detail
7399-
[Tags] registry tls_proxied
7400+
[Tags] registry_extension tls_proxied
74007401
${inputStr} = Catenate
74017402
... SELECT region, instance_id, tenancy, security_groups
74027403
... FROM aws.ec2_nextgen.instances

0 commit comments

Comments
 (0)