robotframework-robotlog2rqm 1.6.0__tar.gz → 1.7.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. {robotframework_robotlog2rqm-1.6.0/robotframework_robotlog2rqm.egg-info → robotframework_robotlog2rqm-1.7.1}/PKG-INFO +1 -1
  2. {robotframework_robotlog2rqm-1.6.0 → robotframework_robotlog2rqm-1.7.1}/RobotLog2RQM/CRQM.py +33 -10
  3. robotframework_robotlog2rqm-1.7.1/RobotLog2RQM/RobotLog2RQM.pdf +0 -0
  4. {robotframework_robotlog2rqm-1.6.0 → robotframework_robotlog2rqm-1.7.1}/RobotLog2RQM/rqmtool.py +52 -4
  5. {robotframework_robotlog2rqm-1.6.0 → robotframework_robotlog2rqm-1.7.1}/RobotLog2RQM/version.py +2 -2
  6. {robotframework_robotlog2rqm-1.6.0 → robotframework_robotlog2rqm-1.7.1/robotframework_robotlog2rqm.egg-info}/PKG-INFO +1 -1
  7. robotframework_robotlog2rqm-1.6.0/RobotLog2RQM/RobotLog2RQM.pdf +0 -0
  8. {robotframework_robotlog2rqm-1.6.0 → robotframework_robotlog2rqm-1.7.1}/LICENSE +0 -0
  9. {robotframework_robotlog2rqm-1.6.0 → robotframework_robotlog2rqm-1.7.1}/README.rst +0 -0
  10. {robotframework_robotlog2rqm-1.6.0 → robotframework_robotlog2rqm-1.7.1}/RobotLog2RQM/RQM_templates/buildrecord.xml +0 -0
  11. {robotframework_robotlog2rqm-1.6.0 → robotframework_robotlog2rqm-1.7.1}/RobotLog2RQM/RQM_templates/configuration.xml +0 -0
  12. {robotframework_robotlog2rqm-1.6.0 → robotframework_robotlog2rqm-1.7.1}/RobotLog2RQM/RQM_templates/executionresult.xml +0 -0
  13. {robotframework_robotlog2rqm-1.6.0 → robotframework_robotlog2rqm-1.7.1}/RobotLog2RQM/RQM_templates/executionworkitem.xml +0 -0
  14. {robotframework_robotlog2rqm-1.6.0 → robotframework_robotlog2rqm-1.7.1}/RobotLog2RQM/RQM_templates/suiteexecutionrecord.xml +0 -0
  15. {robotframework_robotlog2rqm-1.6.0 → robotframework_robotlog2rqm-1.7.1}/RobotLog2RQM/RQM_templates/testcase.xml +0 -0
  16. {robotframework_robotlog2rqm-1.6.0 → robotframework_robotlog2rqm-1.7.1}/RobotLog2RQM/RQM_templates/testsuite.xml +0 -0
  17. {robotframework_robotlog2rqm-1.6.0 → robotframework_robotlog2rqm-1.7.1}/RobotLog2RQM/RQM_templates/testsuitelog.xml +0 -0
  18. {robotframework_robotlog2rqm-1.6.0 → robotframework_robotlog2rqm-1.7.1}/RobotLog2RQM/__init__.py +0 -0
  19. {robotframework_robotlog2rqm-1.6.0 → robotframework_robotlog2rqm-1.7.1}/RobotLog2RQM/__main__.py +0 -0
  20. {robotframework_robotlog2rqm-1.6.0 → robotframework_robotlog2rqm-1.7.1}/RobotLog2RQM/logger.py +0 -0
  21. {robotframework_robotlog2rqm-1.6.0 → robotframework_robotlog2rqm-1.7.1}/RobotLog2RQM/robotlog2rqm.py +0 -0
  22. {robotframework_robotlog2rqm-1.6.0 → robotframework_robotlog2rqm-1.7.1}/robotframework_robotlog2rqm.egg-info/SOURCES.txt +0 -0
  23. {robotframework_robotlog2rqm-1.6.0 → robotframework_robotlog2rqm-1.7.1}/robotframework_robotlog2rqm.egg-info/dependency_links.txt +0 -0
  24. {robotframework_robotlog2rqm-1.6.0 → robotframework_robotlog2rqm-1.7.1}/robotframework_robotlog2rqm.egg-info/entry_points.txt +0 -0
  25. {robotframework_robotlog2rqm-1.6.0 → robotframework_robotlog2rqm-1.7.1}/robotframework_robotlog2rqm.egg-info/requires.txt +0 -0
  26. {robotframework_robotlog2rqm-1.6.0 → robotframework_robotlog2rqm-1.7.1}/robotframework_robotlog2rqm.egg-info/top_level.txt +0 -0
  27. {robotframework_robotlog2rqm-1.6.0 → robotframework_robotlog2rqm-1.7.1}/setup.cfg +0 -0
  28. {robotframework_robotlog2rqm-1.6.0 → robotframework_robotlog2rqm-1.7.1}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: robotframework-robotlog2rqm
3
- Version: 1.6.0
3
+ Version: 1.7.1
4
4
  Summary: Imports robot result(s) to IBM Rational Quality Manager (RQM)
5
5
  Home-page: https://github.com/test-fullautomation/robotframework-robotlog2rqm
6
6
  Author: Tran Duy Ngoan
@@ -2125,11 +2125,21 @@ Link list of test cases to provided testplan ID.
2125
2125
  # use namespace mapping from root for access response XML
2126
2126
  root = oTree.getroot()
2127
2127
 
2128
+ # Collect existing linked TC IDs to avoid duplication
2129
+ lExistingTCIDs = []
2130
+ NS_QM = f"{{{self.NAMESPACES['ns2']}}}"
2131
+ for oTC in root.findall(f'{NS_QM}testcase', root.nsmap):
2132
+ href = oTC.get('href')
2133
+ if href:
2134
+ sTCID = href.split('/')[-1]
2135
+ lExistingTCIDs.append(sTCID)
2136
+
2128
2137
  for sTCID in lTestcases:
2129
- sTestcaseURL = self.integrationURL('testcase', sTCID)
2130
- oTC = etree.Element('{http://jazz.net/xmlns/alm/qm/v0.1/}testcase', nsmap=root.nsmap)
2131
- oTC.set('href', sTestcaseURL)
2132
- root.append(oTC)
2138
+ if sTCID not in lExistingTCIDs:
2139
+ sTestcaseURL = self.integrationURL('testcase', sTCID)
2140
+ oTC = etree.Element(f'{NS_QM}testcase', nsmap=root.nsmap)
2141
+ oTC.set('href', sTestcaseURL)
2142
+ root.append(oTC)
2133
2143
 
2134
2144
  # Update test plan data with linked testcases and PUT to RQM
2135
2145
  resUpdateTestplan = self.updateResourceByID('testplan', testplanID, etree.tostring(oTree))
@@ -2190,13 +2200,26 @@ Link list of test cases to provided testsuite ID
2190
2200
  root = oTree.getroot()
2191
2201
 
2192
2202
  oSuiteElems = oTree.find('ns2:suiteelements', root.nsmap)
2203
+ # Collect existing linked TC IDs to avoid duplication
2204
+ lExistingTCIDs = []
2205
+ NS_QM = f"{{{self.NAMESPACES['ns2']}}}"
2206
+ for oElem in oSuiteElems.findall(f'{NS_QM}suiteelement', root.nsmap):
2207
+ oTC = oElem.find(f'{NS_QM}testcase', root.nsmap)
2208
+ if oTC is not None:
2209
+ href = oTC.get('href')
2210
+ if href:
2211
+ sTCID = href.split('/')[-1]
2212
+ lExistingTCIDs.append(sTCID)
2213
+
2193
2214
  for sTCID in lTestcases:
2194
- sTestcaseURL = self.integrationURL('testcase', sTCID)
2195
- oTC = etree.Element('{http://jazz.net/xmlns/alm/qm/v0.1/}testcase', nsmap=root.nsmap)
2196
- oTC.set('href', sTestcaseURL)
2197
- oElem = etree.Element('{http://jazz.net/xmlns/alm/qm/v0.1/}suiteelement', nsmap=root.nsmap)
2198
- oElem.append(oTC)
2199
- oSuiteElems.append(oElem)
2215
+ if sTCID not in lExistingTCIDs:
2216
+ sTestcaseURL = self.integrationURL('testcase', sTCID)
2217
+ oTC = etree.Element(f'{NS_QM}testcase', nsmap=root.nsmap)
2218
+ oTC.set('href', sTestcaseURL)
2219
+ oElem = etree.Element(f'{NS_QM}suiteelement', nsmap=root.nsmap)
2220
+ oElem.append(oTC)
2221
+ oSuiteElems.append(oElem)
2222
+
2200
2223
  root.append(oSuiteElems)
2201
2224
 
2202
2225
  # Update test suite data with linked testcases and PUT to RQM
@@ -30,6 +30,7 @@ import argparse
30
30
  import os
31
31
  import csv
32
32
  import json
33
+ import base64
33
34
 
34
35
  from RobotLog2RQM.CRQM import CRQMClient
35
36
  from RobotLog2RQM.logger import Logger
@@ -78,12 +79,22 @@ Process provided argument(s) from command line.
78
79
  required=True,
79
80
  help="RQM username."
80
81
  )
81
- parser.add_argument(
82
+ # exclusive group to provide only --password, --password-enc or --password-file
83
+ group_password = parser.add_mutually_exclusive_group(required=True)
84
+ group_password.add_argument(
82
85
  "--password",
83
- required=True,
84
86
  help="RQM password."
85
87
  )
86
- # exclusive group to provdve only --testsuite or --testplan
88
+ group_password.add_argument(
89
+ "--password-enc",
90
+ help="RQM password as base64-encoded string."
91
+ )
92
+ group_password.add_argument(
93
+ "--password-file",
94
+ help="Path to a file containing the password. If the content starts with 'b64:', "
95
+ "the remainder is treated as base64-encoded."
96
+ )
97
+ # exclusive group to provide only --testsuite or --testplan
87
98
  group = parser.add_mutually_exclusive_group(required=True)
88
99
  group.add_argument(
89
100
  "--testplan",
@@ -126,6 +137,36 @@ Process provided argument(s) from command line.
126
137
  help="Base name for output files.")
127
138
  return parser.parse_args()
128
139
 
140
+ def __resolve_password(args):
141
+ """
142
+ Resolve password from --password-enc, --password-file, or --password.
143
+ Order of precedence: password-enc > password-file > password.
144
+ """
145
+ if args.password_enc:
146
+ try:
147
+ return base64.b64decode(args.password_enc).decode("utf-8")
148
+ except Exception as e:
149
+ raise ValueError(f"Failed to decode --password-enc: {e}")
150
+
151
+ if args.password_file:
152
+ if not os.path.isfile(args.password_file):
153
+ raise FileNotFoundError(f"Password file not found: {args.password_file}")
154
+ with open(args.password_file, "r", encoding="utf-8") as f:
155
+ content = f.read().strip()
156
+ # If file content starts with 'b64:', decode the remainder
157
+ if content.startswith("b64:"):
158
+ enc = content[4:]
159
+ try:
160
+ return base64.b64decode(enc).decode("utf-8")
161
+ except Exception as e:
162
+ raise ValueError(f"Failed to decode base64 in password file: {e}")
163
+ return content
164
+
165
+ if args.password:
166
+ return args.password
167
+
168
+ raise ValueError("No password provided. Use --password-enc, --password-file, or --password.")
169
+
129
170
  def __validate_arguments(arguments):
130
171
  """
131
172
  Validate and normalize command line arguments.
@@ -345,7 +386,14 @@ Main entry point for RQMTool CLI.
345
386
  __validate_arguments(args)
346
387
  Logger.config(dryrun=args.dryrun)
347
388
 
348
- RQMClient = CRQMClient(args.user, args.password, args.project, args.host)
389
+ # Resolve password securely (supports base64 and file-based)
390
+ try:
391
+ resolved_password = __resolve_password(args)
392
+ except Exception as reason:
393
+ Logger.log_error(f"Could not resolve password: '{str(reason)}'.")
394
+ return
395
+
396
+ RQMClient = CRQMClient(args.user, resolved_password, args.project, args.host)
349
397
  try:
350
398
  bSuccess = RQMClient.login()
351
399
  RQMClient.config(stream=args.stream, baseline=args.baseline)
@@ -18,5 +18,5 @@
18
18
  #
19
19
  # Version and date of RobotLog2RQM
20
20
  #
21
- VERSION = "1.6.0"
22
- VERSION_DATE = "10.11.2025"
21
+ VERSION = "1.7.1"
22
+ VERSION_DATE = "03.02.2026"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: robotframework-robotlog2rqm
3
- Version: 1.6.0
3
+ Version: 1.7.1
4
4
  Summary: Imports robot result(s) to IBM Rational Quality Manager (RQM)
5
5
  Home-page: https://github.com/test-fullautomation/robotframework-robotlog2rqm
6
6
  Author: Tran Duy Ngoan