Skip to content

Re-attempt block disappearing scope file #692

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

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all 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
4 changes: 4 additions & 0 deletions docs/reference/analysis-scope-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,10 @@ We recommend you add `sigrid.yaml` to your repository, so that it is automatical

- If you want to *retrieve* the scope configuration file used by Sigrid, you can use the [Sigrid API](../integrations/sigrid-api-documentation.md). You can also use the [example code on GitHub](https://github.com/Software-Improvement-Group/sigrid-integrations/tree/main/get-scope-file) for this.
- If you want to *update* the scope configuration file, independently of your source code, you can still use [Sigrid CI](client-script-usage.md). You can also use the [example code on GitHub](https://github.com/Software-Improvement-Group/sigrid-integrations/tree/main/get-scope-file) for this.

## Removing the scope configuration file

Once you have decided to create a scope configuration file to customize your Sigrid configuration, there is no way to go back. If you try to delete the `sigrid.yaml` file from your repository, you will receive an error message when trying to run Sigrid CI.

## Sigrid metadata

Expand Down
29 changes: 19 additions & 10 deletions sigridci/sigridci/sigridci_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ class SigridCiRunner:
"remark"
]

DOCS_URL = "https://docs.sigrid-says.com"
MISSING_SCOPE_URL = f"{DOCS_URL}/reference/analysis-scope-configuration.html#removing-the-scope-configuration-file"

def __init__(self, options: PublishOptions, apiClient: SigridApiClient):
self.options = options
self.apiClient = apiClient
Expand All @@ -67,21 +70,22 @@ def run(self):
systemExists = self.apiClient.checkSystemExists()
UploadLog.log("Found system in Sigrid" if systemExists else "System is not yet on-boarded to Sigrid")

if systemExists and not self.apiClient.fetchMetadata().get("active", True):
UploadLog.log("Publish blocked: System has been deactivated by your Sigrid administrator, in the Sigrid system settings page")
metadata = self.apiClient.fetchMetadata() if systemExists else {}
if systemExists and not metadata.get("active", True):
UploadLog.log("Publish blocked: System has been deactivated by your Sigrid administrator in the Sigrid system settings page")
sys.exit(1)

self.prepareMetadata()
self.validateConfigurationFiles()
self.validateConfigurationFiles(metadata)
analysisId = self.apiClient.submitUpload(systemExists)

if not systemExists:
UploadLog.log(f"System '{self.options.system}' has been on-boarded and will appear in Sigrid shortly")
elif self.options.runMode == RunMode.PUBLISH_ONLY:
UploadLog.log("Your project's source code has been published to Sigrid")
self.displayMetadata()
self.displayMetadata(metadata)
else:
self.displayFeedback(analysisId)
self.displayFeedback(analysisId, metadata)

def prepareRun(self):
# We don't use the options.feedbackURL directly, since that's intended
Expand All @@ -90,27 +94,32 @@ def prepareRun(self):
if self.options.feedbackURL:
self.apiClient.logPlatformInformation(Platform.getPlatformId())

def displayFeedback(self, analysisId):
def displayFeedback(self, analysisId, metadata):
if self.options.targetRating == "sigrid":
self.options.targetRating = self.loadSigridTarget()

feedback = self.apiClient.fetchAnalysisResults(analysisId)
self.displayMetadata()
self.displayMetadata(metadata)

if not os.path.exists(self.options.outputDir):
os.mkdir(self.options.outputDir)

for report in self.reports:
report.generate(analysisId, feedback, self.options)

def validateConfigurationFiles(self):
def validateConfigurationFiles(self, metadata):
scope = self.options.readScopeFile()

if scope is not None:
if self.options.subsystem not in (None, "", "root", "scopefile"):
UploadLog.log("Warning: You cannot provide a scope configuration file for a subsystem, it will be ignored.")

self.validateConfiguration(lambda: self.apiClient.validateScopeFile(scope), "scope configuration file")

if scope is None and metadata.get("scopeFileInRepository") and not self.options.subsystem:
message = {"valid" : False, "notes" : ["Missing sigrid.yaml file", f"See {self.MISSING_SCOPE_URL}"]}
self.validateConfiguration(lambda: message, "scope configuration file")

metadataFile = self.options.readMetadataFile()
if metadataFile is not None:
self.validateConfiguration(lambda: self.apiClient.validateMetadata(metadataFile), "Sigrid metadata file")
Expand All @@ -129,11 +138,11 @@ def validateConfiguration(self, validationCall, configurationName):
UploadLog.log("-" * 80)
sys.exit(1)

def displayMetadata(self):
def displayMetadata(self, metadata):
if self.options.readMetadataFile() == None:
print("")
print("Sigrid metadata for this system:")
for key, value in self.apiClient.fetchMetadata().items():
for key, value in metadata.items():
if value:
print(f" {key}:".ljust(20) + str(value))

Expand Down
79 changes: 70 additions & 9 deletions test/test_sigridci_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ def testRegularRun(self):
"/analysis-results/api/v1/system-metadata/aap/noot",
"/inboundresults/sig/aap/noot/ci/uploads/v1",
"UPLOAD",
"/analysis-results/sigridci/aap/noot/v1/ci/results/123",
"/analysis-results/api/v1/system-metadata/aap/noot"
"/analysis-results/sigridci/aap/noot/v1/ci/results/123"
]

self.assertEqual(UploadLog.history, expectedLog)
Expand Down Expand Up @@ -109,8 +108,7 @@ def testPublishRun(self):
"/analysis-results/api/v1/system-metadata/aap/noot",
"/inboundresults/sig/aap/noot/ci/uploads/v1/publish",
"UPLOAD",
"/analysis-results/sigridci/aap/noot/v1/ci/results/123",
"/analysis-results/api/v1/system-metadata/aap/noot"
"/analysis-results/sigridci/aap/noot/v1/ci/results/123"
]

self.assertEqual(UploadLog.history, expectedLog)
Expand Down Expand Up @@ -143,8 +141,7 @@ def testPublishOnlyRun(self):
"/analysis-results/sigridci/aap/noot/v1/ci",
"/analysis-results/api/v1/system-metadata/aap/noot",
"/inboundresults/sig/aap/noot/ci/uploads/v1/publishonly",
"UPLOAD",
"/analysis-results/api/v1/system-metadata/aap/noot"
"UPLOAD"
]

self.assertEqual(UploadLog.history, expectedLog)
Expand Down Expand Up @@ -196,8 +193,7 @@ def testAddSubsystemOptionToUrl(self):
"/analysis-results/api/v1/system-metadata/aap/noot",
"/inboundresults/sig/aap/noot/ci/uploads/v1/publish?subsystem=mysubsystem",
"UPLOAD",
"/analysis-results/sigridci/aap/noot/v1/ci/results/123",
"/analysis-results/api/v1/system-metadata/aap/noot"
"/analysis-results/sigridci/aap/noot/v1/ci/results/123"
]

self.assertEqual(apiClient.called, expectedCalls)
Expand Down Expand Up @@ -623,7 +619,7 @@ def testSkipForDeactivatedSystems(self):
expectedLog = [
"Using token ending in '****ummy'",
"Found system in Sigrid",
"Publish blocked: System has been deactivated by your Sigrid administrator, in the Sigrid system settings page"
"Publish blocked: System has been deactivated by your Sigrid administrator in the Sigrid system settings page"
]

expectedCalls = [
Expand All @@ -634,6 +630,71 @@ def testSkipForDeactivatedSystems(self):
self.assertEqual(UploadLog.history, expectedLog)
self.assertEqual(apiClient.called, expectedCalls)

def testMissingScopeFileIsNotErrorIfNoPreviousScopeFileExists(self):
apiClient = MockApiClient(self.options)
apiClient.responses["/inboundresults/sig/aap/noot/ci/validate/v1"] = {"valid" : True, "notes" : []}
apiClient.responses["/analysis-results/api/v1/system-metadata/aap/noot"] = {"scopeFileInRepository" : False}

runner = SigridCiRunner(self.options, apiClient)
runner.reports = []

with self.assertRaises(SystemExit):
runner.run()

expectedLog = [
"Using token ending in '****ummy'",
"Found system in Sigrid",
"Creating upload",
"Upload size is 1 MB"
]

self.assertEqual(UploadLog.history, expectedLog)

def testMissingScopeFileIsErrorIfPreviousScopeFileExists(self):
apiClient = MockApiClient(self.options)
apiClient.responses["/inboundresults/sig/aap/noot/ci/validate/v1"] = {"valid" : True, "notes" : []}
apiClient.responses["/analysis-results/api/v1/system-metadata/aap/noot"] = {"scopeFileInRepository" : True}

runner = SigridCiRunner(self.options, apiClient)
runner.reports = []

with self.assertRaises(SystemExit):
runner.run()

expectedLog = [
"Using token ending in '****ummy'",
"Found system in Sigrid",
"Validating scope configuration file",
"--------------------------------------------------------------------------------",
"Invalid scope configuration file:",
" - Missing sigrid.yaml file",
" - See https://docs.sigrid-says.com/reference/analysis-scope-configuration.html#removing-the-scope-configuration-file",
"--------------------------------------------------------------------------------"
]

self.assertEqual(UploadLog.history, expectedLog)

def testMissingScopeFileIsFineForSubsystems(self):
apiClient = MockApiClient(self.options)
apiClient.responses["/inboundresults/sig/aap/noot/ci/validate/v1"] = {"valid" : True, "notes" : []}
apiClient.responses["/analysis-results/api/v1/system-metadata/aap/noot"] = {"scopeFileInRepository" : True}

self.options.subsystem = "aap"
runner = SigridCiRunner(self.options, apiClient)
runner.reports = []

with self.assertRaises(SystemExit):
runner.run()

expectedLog = [
"Using token ending in '****ummy'",
"Found system in Sigrid",
"Creating upload",
"Upload size is 1 MB"
]

self.assertEqual(UploadLog.history, expectedLog)

def createTempFile(self, dir, name, contents):
with open(f"{dir}/{name}", "w") as fileRef:
fileRef.write(contents)
Expand Down