diff --git a/CHANGELOG.md b/CHANGELOG.md
index f221bc8cee..0cdb9223dc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,7 @@
# Changelog
## Unreleased
+- Change initial project validation to take into account non GxP requirement([#1006](https://github.com/opendevstack/ods-jenkins-shared-library/pull/1006))
- Make IS_GXP property available for CFTP documents ([#996](https://github.com/opendevstack/ods-jenkins-shared-library/issues/996))
- Use a consistent notion of document version and remove header ([#987](https://github.com/opendevstack/ods-jenkins-shared-library/issues/987))
- Improve Document Generation Experience ([#991](https://github.com/opendevstack/ods-jenkins-shared-library/issues/991))
diff --git a/src/org/ods/orchestration/usecase/JiraUseCase.groovy b/src/org/ods/orchestration/usecase/JiraUseCase.groovy
index 1f9f2995af..811c5eb802 100644
--- a/src/org/ods/orchestration/usecase/JiraUseCase.groovy
+++ b/src/org/ods/orchestration/usecase/JiraUseCase.groovy
@@ -380,6 +380,7 @@ class JiraUseCase {
def releaseStatusIssueKey = this.project.buildParams.releaseStatusJiraIssueKey
if (message) {
String commentToAdd = "${message}\n\nSee: ${this.steps.env.RUN_DISPLAY_URL}"
+ commentToAdd += "\n\nPlease note that for a successful Deploy to D, the above-mentioned issues need to be in status Done."
logger.debug("Adding comment to Jira issue with key ${releaseStatusIssueKey}: ${commentToAdd}")
this.jira.appendCommentToIssue(releaseStatusIssueKey, commentToAdd)
logger.info("Comment was added to Jira issue with key ${releaseStatusIssueKey}: ${commentToAdd}")
diff --git a/src/org/ods/orchestration/usecase/LeVADocumentUseCase.groovy b/src/org/ods/orchestration/usecase/LeVADocumentUseCase.groovy
index d26963e7f5..50ad872a5b 100644
--- a/src/org/ods/orchestration/usecase/LeVADocumentUseCase.groovy
+++ b/src/org/ods/orchestration/usecase/LeVADocumentUseCase.groovy
@@ -50,7 +50,7 @@ import java.time.LocalDateTime
'PublicMethodsBeforeNonPublicMethods'])
class LeVADocumentUseCase extends DocGenUseCase {
- protected static final boolean IS_GXP_PROJECT_DEFAULT = true
+ private static final String NOT_MANDATORY_CONTENT = 'Not mandatory.'
protected static Map DOCUMENT_TYPE_NAMES = [
(DocumentType.CSD as String) : 'Combined Specification Document',
@@ -1000,20 +1000,14 @@ class LeVADocumentUseCase extends DocGenUseCase {
sections: sections,
documentHistory: docHistory?.getDocGenFormat() ?: [],
documentHistoryLatestVersionId: docHistory?.latestVersionId ?: 1,
- isGxpProject: isGxpProject(this.project.getProjectProperties()),
+ isGxpProject: this.project.isGxpProject(),
]
]
-
def uri = this.createDocument(documentType, null, data_, [:], null, getDocumentTemplateName(documentType), watermarkText)
this.updateJiraDocumentationTrackingIssue(documentType, uri, docHistory?.getVersion() as String)
return uri
}
- protected boolean isGxpProject(Map projectProperties) {
- String isGxp = projectProperties."PROJECT.IS_GXP"
- return isGxp != null ? isGxp.toBoolean() : IS_GXP_PROJECT_DEFAULT
- }
-
@NonCPS
private def computeKeysInDocForTIP(def data) {
return data.collect { it.key }
@@ -1528,7 +1522,7 @@ class LeVADocumentUseCase extends DocGenUseCase {
date_created : LocalDateTime.now().toString(),
buildParameter: this.project.buildParams,
git : repo ? repo.data.git : this.project.gitData,
- gxp : isGxpProject(this.project.getProjectProperties()),
+ gxp : project.isGxpProject(),
openShift : [apiUrl: this.project.getOpenShiftApiUrl()],
jenkins : [
buildNumber: this.steps.env.BUILD_NUMBER,
@@ -1693,10 +1687,14 @@ class LeVADocumentUseCase extends DocGenUseCase {
throw new RuntimeException("Error: unable to create ${documentType}. " +
'Could not obtain document chapter data from Jira.')
}
- // Extract-out the section, as needed for the DocGen interface
- return sections.collectEntries { sec ->
- [(sec.section): sec + [content: this.convertImages(sec.content)]]
+
+ def sectionCollection = sections.collectEntries { sec ->
+ [(sec.section): sec + [content: this.project.replaceIssueContentWithNonMandatoryText(sec) ?
+ '
' + this.NOT_MANDATORY_CONTENT + '
' : this.convertImages(sec.content)]]
}
+
+ // Extract-out the section, as needed for the DocGen interface
+ return sectionCollection
}
protected Map getDocumentSectionsFileOptional(String documentType) {
diff --git a/src/org/ods/orchestration/util/MROPipelineUtil.groovy b/src/org/ods/orchestration/util/MROPipelineUtil.groovy
index b0f07ed146..48bbe2711f 100644
--- a/src/org/ods/orchestration/util/MROPipelineUtil.groovy
+++ b/src/org/ods/orchestration/util/MROPipelineUtil.groovy
@@ -10,7 +10,6 @@ import org.ods.orchestration.dependency.DependencyGraph
import org.ods.orchestration.dependency.Node
import org.ods.services.OpenShiftService
import org.ods.services.ServiceRegistry
-import org.ods.orchestration.util.DeploymentDescriptor
import org.ods.orchestration.phases.DeployOdsComponent
import org.ods.orchestration.phases.FinalizeOdsComponent
import org.ods.orchestration.phases.FinalizeNonOdsComponent
@@ -21,6 +20,7 @@ import org.yaml.snakeyaml.Yaml
class MROPipelineUtil extends PipelineUtil {
class PipelineConfig {
+
// TODO: deprecate .pipeline-config.yml in favor of release-manager.yml
static final List FILE_NAMES = ["release-manager.yml", ".pipeline-config.yml"]
@@ -36,23 +36,27 @@ class MROPipelineUtil extends PipelineUtil {
static final List PHASE_EXECUTOR_TYPES = [
PHASE_EXECUTOR_TYPE_MAKEFILE,
- PHASE_EXECUTOR_TYPE_SHELLSCRIPT
+ PHASE_EXECUTOR_TYPE_SHELLSCRIPT,
]
static final List INSTALLABLE_REPO_TYPES = [
REPO_TYPE_ODS_CODE as String,
REPO_TYPE_ODS_SERVICE as String,
- REPO_TYPE_ODS_INFRA as String
+ REPO_TYPE_ODS_INFRA as String,
]
+
}
class PipelineEnvs {
+
static final String DEV = "dev"
static final String QA = "qa"
static final String PROD = "prod"
+
}
class PipelinePhases {
+
static final String BUILD = "Build"
static final String DEPLOY = "Deploy"
static final String FINALIZE = "Finalize"
@@ -61,6 +65,7 @@ class MROPipelineUtil extends PipelineUtil {
static final String TEST = "Test"
static final List ALWAYS_PARALLEL = []
+
}
static final String COMPONENT_METADATA_FILE_NAME = 'metadata.yml'
@@ -88,46 +93,6 @@ class MROPipelineUtil extends PipelineUtil {
}
}
- private void executeODSComponent(Map repo, String baseDir, boolean failfast = true,
- String jenkinsFile = 'Jenkinsfile') {
- this.steps.dir(baseDir) {
- if (repo.data.openshift.resurrectedBuild) {
- logger.info("Repository '${repo.id}' is in sync with OpenShift, no need to rebuild")
- return
- }
- def job
- def env = []
- env.addAll(this.project.getMainReleaseManagerEnv())
- this.project.buildParams.each { key, value ->
- env << "BUILD_PARAM_${key.toUpperCase()}=${value}"
- }
- env << "NOTIFY_BB_BUILD=${!project.isWorkInProgress}"
- this.steps.withEnv (env) {
- job = this.loadGroovySourceFile("${baseDir}/${jenkinsFile}")
- }
- // Collect ODS build artifacts for repo.
- // We get a map with at least two keys ("build" and "deployments").
- def buildArtifacts = job.getBuildArtifactURIs()
- buildArtifacts.each { k, v ->
- if (k != 'failedStage') {
- repo.data.openshift[k] = v
- }
- }
- def versionAndBuild = "${this.project.buildParams.version}/${this.steps.env.BUILD_NUMBER}"
- repo.data.openshift[DeploymentDescriptor.CREATED_BY_BUILD_STR] = versionAndBuild
- this.logger.debug("Collected ODS build artifacts for repo '${repo.id}': ${repo.data.openshift}")
-
- if (buildArtifacts.failedStage) {
- repo.data << ['failedStage': buildArtifacts.failedStage]
- if (failfast) {
- throw new RuntimeException("Error: aborting due to previous errors in repo '${repo.id}'.")
- } else {
- this.logger.warn("Got errors in repo '${repo.id}', will fail delayed.")
- }
- }
- }
- }
-
Map loadPipelineConfig(String path, Map repo) {
if (!path?.trim()) {
throw new IllegalArgumentException("Error: unable to parse pipeline config. 'path' is undefined.")
@@ -226,7 +191,7 @@ class MROPipelineUtil extends PipelineUtil {
repo.id,
{
checkoutNotReleaseManagerRepo(repo, recheckout)
- }
+ },
]
}
@@ -265,7 +230,7 @@ class MROPipelineUtil extends PipelineUtil {
previousSucessfulCommit: lastSuccessCommit,
url: scm.GIT_URL,
baseTag: this.project.baseTag,
- targetTag: this.project.targetTag
+ targetTag: this.project.targetTag,
]
def repoPath = "${this.steps.env.WORKSPACE}/${REPOS_BASE_DIR}/${repo.id}"
loadPipelineConfig(repoPath, repo)
@@ -283,66 +248,6 @@ class MROPipelineUtil extends PipelineUtil {
}
}
- private Map checkOutNotReleaseManagerRepoInNotPromotionMode(Map repo, boolean isWorkInProgress) {
- Map scmResult = [ : ]
- String gitReleaseBranch = this.project.gitReleaseBranch
- if ("master" == gitReleaseBranch) {
- gitReleaseBranch = repo.branch
- }
-
- // check if release manager repo already has a release branch
- if (git.remoteBranchExists(gitReleaseBranch)) {
- try {
- scmResult.scm = checkoutBranchInRepoDir(repo, gitReleaseBranch)
- scmResult.scmBranch = gitReleaseBranch
- } catch (ex) {
- if (! isWorkInProgress) {
- this.logger.warn """
- Checkout of '${gitReleaseBranch}' for repo '${repo.id}' failed.
- Attempting to checkout '${repo.branch}' and create the release branch from it.
- """
- // Possible reasons why this might happen:
- // * Release branch manually created in RM repo
- // * Repo is added to metadata.yml file on a release branch
- // * Release branch has been deleted in repo
-
- scmResult.scm = createBranchFromDefaultBranch(repo, gitReleaseBranch)
- scmResult.scmBranch = gitReleaseBranch
- } else {
- this.logger.warn """
- Checkout of '${gitReleaseBranch}' for repo '${repo.id}' failed.
- Attempting to checkout branch '${repo.branch}'.
- """
- scmResult.scm = checkoutBranchInRepoDir(repo, repo.branch)
- scmResult.scmBranch = repo.branch
- }
- }
- } else {
- if (! isWorkInProgress) {
- scmResult.scm = createBranchFromDefaultBranch(repo, gitReleaseBranch)
- scmResult.scmBranch = gitReleaseBranch
- } else {
- this.logger.info("Since in WIP and no release branch exists (${this.project.gitReleaseBranch}), checking out branch ${repo.branch} for repo ${repo.id}")
- scmResult.scm = checkoutBranchInRepoDir(repo, repo.branch)
- scmResult.scmBranch = repo.branch
- }
- }
- return scmResult
- }
-
- private def createBranchFromDefaultBranch(Map repo, String branchName) {
- this.logger.info("Creating branch ${branchName} from branch ${repo.branch} for repo ${repo.id} ")
- def scm = checkoutBranchInRepoDir(repo, repo.branch)
- if (repo.branch != branchName) {
- steps.dir("${REPOS_BASE_DIR}/${repo.id}") {
- git.checkoutNewLocalBranch(branchName)
- }
- } else {
- this.logger.info("No need to create branch ${branchName} for repo ${repo.id} ")
- }
- return scm
- }
-
def checkoutTagInRepoDir(Map repo, String tag) {
this.logger.info("Checkout tag ${repo.id}@${tag}")
def credentialsId = this.project.services.bitbucket.credentials.id
@@ -460,7 +365,7 @@ class MROPipelineUtil extends PipelineUtil {
postExecute(this.steps, repo)
}
}
- }
+ },
]
}
@@ -497,6 +402,106 @@ class MROPipelineUtil extends PipelineUtil {
}
}
+ private void executeODSComponent(Map repo, String baseDir, boolean failfast = true,
+ String jenkinsFile = 'Jenkinsfile') {
+ this.steps.dir(baseDir) {
+ if (repo.data.openshift.resurrectedBuild) {
+ logger.info("Repository '${repo.id}' is in sync with OpenShift, no need to rebuild")
+ return
+ }
+ def job
+ def env = []
+ env.addAll(this.project.getMainReleaseManagerEnv())
+ this.project.buildParams.each { key, value ->
+ env << "BUILD_PARAM_${key.toUpperCase()}=${value}"
+ }
+ env << "NOTIFY_BB_BUILD=${!project.isWorkInProgress}"
+ this.steps.withEnv (env) {
+ job = this.loadGroovySourceFile("${baseDir}/${jenkinsFile}")
+ }
+ // Collect ODS build artifacts for repo.
+ // We get a map with at least two keys ("build" and "deployments").
+ def buildArtifacts = job.getBuildArtifactURIs()
+ buildArtifacts.each { k, v ->
+ if (k != 'failedStage') {
+ repo.data.openshift[k] = v
+ }
+ }
+ def versionAndBuild = "${this.project.buildParams.version}/${this.steps.env.BUILD_NUMBER}"
+ repo.data.openshift[DeploymentDescriptor.CREATED_BY_BUILD_STR] = versionAndBuild
+ this.logger.debug("Collected ODS build artifacts for repo '${repo.id}': ${repo.data.openshift}")
+
+ if (buildArtifacts.failedStage) {
+ repo.data << ['failedStage': buildArtifacts.failedStage]
+ if (failfast) {
+ throw new RuntimeException("Error: aborting due to previous errors in repo '${repo.id}'.")
+ } else {
+ this.logger.warn("Got errors in repo '${repo.id}', will fail delayed.")
+ }
+ }
+ }
+ }
+
+ private Map checkOutNotReleaseManagerRepoInNotPromotionMode(Map repo, boolean isWorkInProgress) {
+ Map scmResult = [ : ]
+ String gitReleaseBranch = this.project.gitReleaseBranch
+ if ("master" == gitReleaseBranch) {
+ gitReleaseBranch = repo.branch
+ }
+
+ // check if release manager repo already has a release branch
+ if (git.remoteBranchExists(gitReleaseBranch)) {
+ try {
+ scmResult.scm = checkoutBranchInRepoDir(repo, gitReleaseBranch)
+ scmResult.scmBranch = gitReleaseBranch
+ } catch (ex) {
+ if (! isWorkInProgress) {
+ this.logger.warn """
+ Checkout of '${gitReleaseBranch}' for repo '${repo.id}' failed.
+ Attempting to checkout '${repo.branch}' and create the release branch from it.
+ """
+ // Possible reasons why this might happen:
+ // * Release branch manually created in RM repo
+ // * Repo is added to metadata.yml file on a release branch
+ // * Release branch has been deleted in repo
+
+ scmResult.scm = createBranchFromDefaultBranch(repo, gitReleaseBranch)
+ scmResult.scmBranch = gitReleaseBranch
+ } else {
+ this.logger.warn """
+ Checkout of '${gitReleaseBranch}' for repo '${repo.id}' failed.
+ Attempting to checkout branch '${repo.branch}'.
+ """
+ scmResult.scm = checkoutBranchInRepoDir(repo, repo.branch)
+ scmResult.scmBranch = repo.branch
+ }
+ }
+ } else {
+ if (! isWorkInProgress) {
+ scmResult.scm = createBranchFromDefaultBranch(repo, gitReleaseBranch)
+ scmResult.scmBranch = gitReleaseBranch
+ } else {
+ this.logger.info("Since in WIP and no release branch exists (${this.project.gitReleaseBranch}), checking out branch ${repo.branch} for repo ${repo.id}")
+ scmResult.scm = checkoutBranchInRepoDir(repo, repo.branch)
+ scmResult.scmBranch = repo.branch
+ }
+ }
+ return scmResult
+ }
+
+ private createBranchFromDefaultBranch(Map repo, String branchName) {
+ this.logger.info("Creating branch ${branchName} from branch ${repo.branch} for repo ${repo.id} ")
+ def scm = checkoutBranchInRepoDir(repo, repo.branch)
+ if (repo.branch != branchName) {
+ steps.dir("${REPOS_BASE_DIR}/${repo.id}") {
+ git.checkoutNewLocalBranch(branchName)
+ }
+ } else {
+ this.logger.info("No need to create branch ${branchName} for repo ${repo.id} ")
+ }
+ return scm
+ }
+
private boolean isRepoModified(Map repo) {
if (!repo.data.envStateCommit) {
logger.debug("Last recorded commit of '${repo.id}' cannot be retrieved.")
@@ -583,7 +588,7 @@ class MROPipelineUtil extends PipelineUtil {
OpenShiftService.DEPLOYMENTCONFIG_KIND,
deploymentDescriptor.deploymentNames
)
- } catch(ex) {
+ } catch (ex) {
logger.info(
"Resurrection of previous build for '${repo.id}' not possible as " +
"not all deployments could be retrieved: ${ex.message}"
@@ -613,4 +618,5 @@ class MROPipelineUtil extends PipelineUtil {
repo.data.openshift.deployments = deployments
logger.debug("Data from previous Jenkins build:\r${repo.data.openshift}")
}
+
}
diff --git a/src/org/ods/orchestration/util/Project.groovy b/src/org/ods/orchestration/util/Project.groovy
index 3ffcfac169..26852066b3 100644
--- a/src/org/ods/orchestration/util/Project.groovy
+++ b/src/org/ods/orchestration/util/Project.groovy
@@ -27,7 +27,9 @@ import java.nio.file.Paths
'PublicMethodsBeforeNonPublicMethods'])
class Project {
+ static final String IS_GXP_PROJECT_PROPERTY = 'PROJECT.IS_GXP'
static final String DEFAULT_TEMPLATE_VERSION = '1.2'
+ static final boolean IS_GXP_PROJECT_DEFAULT = true
class JiraDataItem implements Map, Serializable {
static final String TYPE_BUGS = 'bugs'
@@ -64,16 +66,17 @@ class Project {
TYPE_DOCS,
]
- static final List TYPES_TO_BE_CLOSED = [
+ static final List COMMON_TYPES_TO_BE_CLOSED = [
+ TYPE_BUGS,
TYPE_EPICS,
TYPE_MITIGATIONS,
TYPE_REQUIREMENTS,
TYPE_RISKS,
TYPE_TECHSPECS,
TYPE_TESTS,
- TYPE_DOCS,
]
+ static final String ISSUE_STATUS_TODO = 'to do'
static final String ISSUE_STATUS_DONE = 'done'
static final String ISSUE_STATUS_CANCELLED = 'cancelled'
@@ -373,7 +376,7 @@ class Project {
this.logger.warn "WIP_Jira_Issues: ${this.data.jira.undone}"
String message = ProjectMessagesUtil.generateWIPIssuesMessage(this)
- if(!this.isWorkInProgress){
+ if (!this.isWorkInProgress){
throw new OpenIssuesException(message)
}
@@ -381,7 +384,7 @@ class Project {
this.addCommentInReleaseStatus(message)
}
- if(this.jiraUseCase.jira) {
+ if (this.jiraUseCase.jira) {
logger.debug("Verify that each unit test in Jira project ${this.key} has exactly one component assigned.")
def faultMap = [:]
this.data.jira.tests
@@ -391,7 +394,7 @@ class Project {
faultMap.put(entry.key, entry.value.get("components").size())
}
}
- if(faultMap.size() != 0) {
+ if (faultMap.size() != 0) {
def faultyTestIssues = faultMap.keySet()
.collect { key -> key + ": " + faultMap.get(key) + "; " }
.inject("") { temp, val -> temp + val }
@@ -419,23 +422,12 @@ class Project {
return !values.isEmpty()
}
- @NonCPS
- boolean isProjectReadyToFreeze(Map data) {
- def result = true
- JiraDataItem.TYPES_TO_BE_CLOSED.each { type ->
- if (data.containsKey(type)) {
- result = result & (data[type].find { k, v -> issueIsWIP(v) } == null)
- }
- }
- return result
- }
-
@NonCPS
protected Map computeWipJiraIssues(Map data) {
- def result = [:]
+ Map result = [:]
JiraDataItem.TYPES_WITH_STATUS.each { type ->
if (data.containsKey(type)) {
- result[type] = data[type].findAll { k, v -> issueIsWIP(v) }.keySet() as List
+ result[type] = data[type].findAll { k, v -> issueIsWIPandMandatory(v, type) }.keySet() as List
}
}
return result
@@ -449,9 +441,11 @@ class Project {
*/
@NonCPS
protected Map computeWipDocChapterPerDocument(Map data) {
- (data[JiraDataItem.TYPE_DOCS] ?: [:])
+ Map result = [:]
+
+ result = (data[JiraDataItem.TYPE_DOCS] ?: [:])
.values()
- .findAll { issueIsWIP(it) }
+ .findAll { v -> issueIsWIPandMandatory(v, JiraDataItem.TYPE_DOCS) }
.collect { chapter ->
chapter.documents.collect { [doc: it, key: chapter.key] }
}.flatten()
@@ -459,13 +453,33 @@ class Project {
.collectEntries { doc, issues ->
[(doc as String): issues.collect { it.key } as List]
}
+
+ return result
}
@NonCPS
- protected boolean issueIsWIP(Map issue) {
- issue.status != null &&
- !issue.status.equalsIgnoreCase(JiraDataItem.ISSUE_STATUS_DONE) &&
- !issue.status.equalsIgnoreCase(JiraDataItem.ISSUE_STATUS_CANCELLED)
+ protected boolean isNonGxpManadatoryDoc(Map doc) {
+ return (doc.documents != null
+ && doc.number != null
+ && ((doc.documents.contains('CSD') && doc.number in ['1', '3.1']) ||
+ (doc.documents.contains('SSDS') && doc.number in ['1', '2.1', '3.1', '5.4'])))
+ }
+
+ @NonCPS
+ protected boolean issueIsWIPandMandatory(Map issue, String type) {
+ if (this.isGxpProject() || type != JiraDataItem.TYPE_DOCS) {
+ return (issue.status != null &&
+ !issue.status.equalsIgnoreCase(JiraDataItem.ISSUE_STATUS_DONE) &&
+ !issue.status.equalsIgnoreCase(JiraDataItem.ISSUE_STATUS_CANCELLED))
+ } else {
+ return (isNonGxpManadatoryDoc(issue) && (issue.status != null &&
+ !issue.status.equalsIgnoreCase(JiraDataItem.ISSUE_STATUS_DONE)))
+ }
+ }
+
+ @NonCPS
+ boolean replaceIssueContentWithNonMandatoryText(Map issue) {
+ return !isGxpProject() && !issueIsWIPandMandatory(issue, JiraDataItem.TYPE_DOCS)
}
@NonCPS
@@ -524,6 +538,7 @@ class Project {
return this.data.jira.project.enumDictionary[name]
}
+ @NonCPS
Map getProjectProperties() {
return this.data.jira.project.projectProperties
}
@@ -589,6 +604,12 @@ class Project {
"${MROPipelineUtil.ODS_STATE_DIR}/${targetEnvironment}.json"
}
+ @NonCPS
+ boolean isGxpProject() {
+ String isGxp = projectProperties?."PROJECT.IS_GXP"
+ return isGxp != null ? isGxp.toBoolean() : IS_GXP_PROJECT_DEFAULT
+ }
+
String getEnvStateFileName() {
envStateFileName(buildParams.targetEnvironment)
}
@@ -1580,7 +1601,6 @@ class Project {
new ProjectDataBitbucketRepository(steps).loadFile(savedVersion)
}
-
/**
* Saves the project data to the
* @return filenames saved
diff --git a/test/groovy/org/ods/orchestration/usecase/JiraUseCaseSpec.groovy b/test/groovy/org/ods/orchestration/usecase/JiraUseCaseSpec.groovy
index 7ae0427dfe..20a29c4061 100644
--- a/test/groovy/org/ods/orchestration/usecase/JiraUseCaseSpec.groovy
+++ b/test/groovy/org/ods/orchestration/usecase/JiraUseCaseSpec.groovy
@@ -861,7 +861,9 @@ class JiraUseCaseSpec extends SpecHelper {
])
then:
- 1 * jira.appendCommentToIssue("JIRA-4711", "${error.message}\n\nSee: ${steps.env.RUN_DISPLAY_URL}")
+ 1 * jira.appendCommentToIssue("JIRA-4711",
+ "${error.message}\n\nSee: ${steps.env.RUN_DISPLAY_URL}" +
+ "\n\nPlease note that for a successful Deploy to D, the above-mentioned issues need to be in status Done.")
}
def "update Jira release status result without error"() {
diff --git a/test/groovy/org/ods/orchestration/usecase/LeVADocumentUseCaseSpec.groovy b/test/groovy/org/ods/orchestration/usecase/LeVADocumentUseCaseSpec.groovy
index 9aa15f18b2..dd9cad88c6 100644
--- a/test/groovy/org/ods/orchestration/usecase/LeVADocumentUseCaseSpec.groovy
+++ b/test/groovy/org/ods/orchestration/usecase/LeVADocumentUseCaseSpec.groovy
@@ -17,9 +17,13 @@ import org.ods.orchestration.service.*
import org.ods.orchestration.util.*
import org.ods.util.IPipelineSteps
import org.ods.util.Logger
+
+import javax.swing.text.Document
import java.nio.file.Files
import java.nio.file.NoSuchFileException
+import static org.ods.orchestration.usecase.DocumentType.*
+import static org.ods.orchestration.usecase.DocumentType.CSD
import static util.FixtureHelper.*
import util.*
@@ -371,11 +375,11 @@ class LeVADocumentUseCaseSpec extends SpecHelper {
where:
documentType || template
- DocumentType.CSD as String || (DocumentType.CSD as String) + "-999"
- DocumentType.SSDS as String || (DocumentType.SSDS as String) + "-999"
- DocumentType.CFTP as String || (DocumentType.CFTP as String) + "-999"
- DocumentType.CFTR as String || (DocumentType.CFTR as String) + "-999"
- DocumentType.RA as String || (DocumentType.RA as String)
+ CSD as String || (CSD as String) + "-999"
+ SSDS as String || (SSDS as String) + "-999"
+ CFTP as String || (CFTP as String) + "-999"
+ CFTR as String || (CFTR as String) + "-999"
+ RA as String || (RA as String)
}
def "create CSD"() {
@@ -384,7 +388,7 @@ class LeVADocumentUseCaseSpec extends SpecHelper {
usecase = Spy(new LeVADocumentUseCase(project, steps, util, docGen, jenkins, jiraUseCase, junit, levaFiles, nexus, os, pdf, sq, bbt, logger))
// Argument Constraints
- def documentType = DocumentType.CSD as String
+ def documentType = CSD as String
// Stubbed Method Responses
def chapterData = ["sec1": [content: "myContent", status: "DONE", key:"DEMO-1"]]
@@ -460,7 +464,7 @@ class LeVADocumentUseCaseSpec extends SpecHelper {
]
// Argument Constraints
- def documentType = DocumentType.TRC as String
+ def documentType = TRC as String
// Stubbed Method Responses
def chapterData = ["sec1": [content: "myContent", status: "DONE", key:"DEMO-1"]]
@@ -491,7 +495,7 @@ class LeVADocumentUseCaseSpec extends SpecHelper {
usecase = Spy(new LeVADocumentUseCase(project, steps, util, docGen, jenkins, jiraUseCase, junit, levaFiles, nexus, os, pdf, sq, bbt, logger))
// Argument Constraints
- def documentType = DocumentType.DIL as String
+ def documentType = DIL as String
def uri = "http://nexus"
def documentTemplate = "template"
def watermarkText = "WATERMARK"
@@ -520,7 +524,7 @@ class LeVADocumentUseCaseSpec extends SpecHelper {
def repo = project.repositories.first()
// Argument Constraints
- def documentType = DocumentType.DTP as String
+ def documentType = DTP as String
// Stubbed Method Responses
def chapterData = ["sec1": [content: "myContent", status: "DONE"]]
@@ -553,7 +557,7 @@ class LeVADocumentUseCaseSpec extends SpecHelper {
def repo = project.repositories.first()
// Argument Constraints
- def documentType = DocumentType.DTP as String
+ def documentType = DTP as String
// Stubbed Method Responses
def chapterData = ["sec1": [content: "myContent", status: "DONE"]]
@@ -600,7 +604,7 @@ class LeVADocumentUseCaseSpec extends SpecHelper {
]
// Argument Constraints
- def documentType = DocumentType.DTR as String
+ def documentType = DTR as String
def files = ["raw/${xmlFile.name}": xmlFile.bytes]
// Stubbed Method Responses
@@ -651,7 +655,7 @@ class LeVADocumentUseCaseSpec extends SpecHelper {
]
// Argument Constraints
- def documentType = DocumentType.DTR as String
+ def documentType = DTR as String
def files = ["raw/${xmlFile.name}": xmlFile.bytes]
// Stubbed Method Responses
@@ -682,7 +686,7 @@ class LeVADocumentUseCaseSpec extends SpecHelper {
usecase = Spy(new LeVADocumentUseCase(project, steps, util, docGen, jenkins, jiraUseCase, junit, levaFiles, nexus, os, pdf, sq, bbt, logger))
// Argument Constraints
- def documentType = DocumentType.CFTP as String
+ def documentType = CFTP as String
// Stubbed Method Responses
def chapterData = ["sec1": [content: "myContent", status: "DONE"]]
@@ -733,7 +737,7 @@ class LeVADocumentUseCaseSpec extends SpecHelper {
]
// Argument Constraints
- def documentType = DocumentType.CFTR as String
+ def documentType = CFTR as String
def files = [ "raw/${xmlFile.name}": xmlFile.bytes ]
// Stubbed Method Responses
@@ -770,7 +774,7 @@ class LeVADocumentUseCaseSpec extends SpecHelper {
usecase = Spy(new LeVADocumentUseCase(project, steps, util, docGen, jenkins, jiraUseCase, junit, levaFiles, nexus, os, pdf, sq, bbt, logger))
// Argument Constraints
- def documentType = DocumentType.TCP as String
+ def documentType = TCP as String
// Stubbed Method Responses
def chapterData = ["sec1": [content: "myContent", status: "DONE"]]
@@ -823,7 +827,7 @@ class LeVADocumentUseCaseSpec extends SpecHelper {
]
// Argument Constraints
- def documentType = DocumentType.TCR as String
+ def documentType = TCR as String
def files = ["raw/${xmlFile.name}": xmlFile.bytes]
// Stubbed Method Responses
@@ -861,7 +865,7 @@ class LeVADocumentUseCaseSpec extends SpecHelper {
usecase = Spy(new LeVADocumentUseCase(project, steps, util, docGen, jenkins, jiraUseCase, junit, levaFiles, nexus, os, pdf, sq, bbt, logger))
// Argument Constraints
- def documentType = DocumentType.IVP as String
+ def documentType = IVP as String
// Stubbed Method Responses
def chapterData = ["sec1": [content: "myContent", status: "DONE"]]
@@ -909,7 +913,7 @@ class LeVADocumentUseCaseSpec extends SpecHelper {
]
// Argument Constraints
- def documentType = DocumentType.IVR as String
+ def documentType = IVR as String
def files = ["raw/${xmlFile.name}": xmlFile.bytes]
// Stubbed Method Responses
@@ -1006,7 +1010,7 @@ class LeVADocumentUseCaseSpec extends SpecHelper {
FileUtils.copyDirectory(new FixtureHelper().getResource("Test-1.pdf").parentFile, tempFolder.getRoot());
def pdfDoc = new FixtureHelper().getResource("Test-1.pdf").bytes
- def documentType = DocumentType.SSDS as String
+ def documentType = SSDS as String
def uri = new URI("http://nexus")
def pdfUtil = new PDFUtil()
jiraUseCase = Spy(new JiraUseCase(project, steps, util, Mock(JiraService), logger))
@@ -1107,7 +1111,7 @@ class LeVADocumentUseCaseSpec extends SpecHelper {
usecase = Spy(new LeVADocumentUseCase(project, steps, util, docGen, jenkins, jiraUseCase, junit, levaFiles, nexus, os, pdf, sq, bbt, logger))
// Argument Constraints
- def documentType = DocumentType.RA as String
+ def documentType = RA as String
// Stubbed Method Responses
def chapterData = ["sec1": [content: "myContent", status: "DONE"]]
@@ -1138,7 +1142,7 @@ class LeVADocumentUseCaseSpec extends SpecHelper {
usecase = Spy(new LeVADocumentUseCase(project, steps, util, docGen, jenkins, jiraUseCase, junit, levaFiles, nexus, os, pdf, sq, bbt, logger))
// Argument Constraints
- def documentType = DocumentType.TIP as String
+ def documentType = TIP as String
// Stubbed Method Responses
def chapterData = ["sec1": [content: "myContent", status: "DONE"]]
@@ -1167,7 +1171,7 @@ class LeVADocumentUseCaseSpec extends SpecHelper {
project.services.jira = null
// Argument Constraints
- def documentType = DocumentType.TIP as String
+ def documentType = TIP as String
// Stubbed Method Responses
def chapterData = ["sec1": [content: "myContent", status: "DONE"]]
@@ -1210,7 +1214,7 @@ class LeVADocumentUseCaseSpec extends SpecHelper {
]
// Argument Constraints
- def documentType = DocumentType.TIR as String
+ def documentType = TIR as String
// Stubbed Method Responses
def chapterData = ["sec1": [content: "myContent", status: "DONE"]]
@@ -1252,7 +1256,7 @@ class LeVADocumentUseCaseSpec extends SpecHelper {
def repo = project.repositories.first()
// Argument Constraints
- def documentType = DocumentType.TIR as String
+ def documentType = TIR as String
// Stubbed Method Responses
def chapterData = ["sec1": [content: "myContent", status: "DONE"]]
@@ -1277,8 +1281,8 @@ class LeVADocumentUseCaseSpec extends SpecHelper {
def "create overall DTR"() {
given:
// Argument Constraints
- def documentType = DocumentType.DTR as String
- def documentTypeName = DocumentType.OVERALL_DTR as String
+ def documentType = DTR as String
+ def documentTypeName = OVERALL_DTR as String
// Stubbed Method Responses
def uri = "http://nexus"
@@ -1296,8 +1300,8 @@ class LeVADocumentUseCaseSpec extends SpecHelper {
def "create overall TIR"() {
given:
// Argument Constraints
- def documentType = DocumentType.TIR as String
- def documentTypeName = DocumentType.OVERALL_TIR as String
+ def documentType = TIR as String
+ def documentTypeName = OVERALL_TIR as String
// Stubbed Method Responses
def uri = "http://nexus"
@@ -1916,22 +1920,40 @@ class LeVADocumentUseCaseSpec extends SpecHelper {
[name: 'NAME',description: 'DESCRIPTION'] | 'DESCRIPTION'
}
- def "verify isGxpProject property"() {
+ def "replace content for non-mandatory open issues"() {
given:
- LeVADocumentUseCase leVADocumentUseCase = new LeVADocumentUseCase(null, null, null,
- null, null, null, null, null, null, null, null,
- null, null, null)
+ jiraUseCase = Spy(new JiraUseCase(project, steps, util, Mock(JiraService), logger))
+ usecase = Spy(new LeVADocumentUseCase(project, steps, util, docGen, jenkins, jiraUseCase, junit, levaFiles, nexus, os, pdf, sq, bbt, logger))
+ project.projectProperties."PROJECT.IS_GXP" = isGxp
+ project.data.jira.docs.doc2 = [
+ documents: documentType,
+ status: status,
+ number: number,
+ section: "sec1",
+ content: "Original content"]
when:
- def result = leVADocumentUseCase.isGxpProject(projectProperties)
+ def result = usecase.getDocumentSections(documentType)
then:
- result == expected
+ result["sec1"].content == expected
where:
- projectProperties | expected
- [:] | LeVADocumentUseCase.IS_GXP_PROJECT_DEFAULT
- ['PROJECT.IS_GXP': 'false'] | false
- ['PROJECT.IS_GXP': 'true'] | true
+ isGxp | documentType | status | number || expected
+ false | CSD as String | "IN PROGRESS" | "2" || "Not mandatory.
"
+ false | SSDS as String | "IN PROGRESS" | "2" || "Not mandatory.
"
+ false | CSD as String | "DONE" | "2" || "Not mandatory.
"
+ false | SSDS as String | "DONE" | "2" || "Not mandatory.
"
+ false | CSD as String | "DONE" | "1" || "Not mandatory.
"
+ false | CSD as String | "CANCELLED" | "2" || "Not mandatory.
"
+ false | SSDS as String | "CANCELLED" | "2" || "Not mandatory.
"
+ false | CSD as String | "IN PROGRESS" | "1" || "Original content"
+ false | CSD as String | "IN PROGRESS" | "3.1" || "Original content"
+ false | SSDS as String | "IN PROGRESS" | "1" || "Original content"
+ false | SSDS as String | "IN PROGRESS" | "2.1" || "Original content"
+ false | SSDS as String | "IN PROGRESS" | "3.1" || "Original content"
+ false | SSDS as String | "IN PROGRESS" | "5.4" || "Original content"
+ true | CSD as String | "IN PROGRESS" | "2" || "Original content"
}
+
}
diff --git a/test/groovy/org/ods/orchestration/util/ProjectSpec.groovy b/test/groovy/org/ods/orchestration/util/ProjectSpec.groovy
index a35d09a96b..fd91eb9b70 100644
--- a/test/groovy/org/ods/orchestration/util/ProjectSpec.groovy
+++ b/test/groovy/org/ods/orchestration/util/ProjectSpec.groovy
@@ -622,6 +622,10 @@ class ProjectSpec extends SpecHelper {
"${type}-3": [
status: "DONE",
key: "${type}-3",
+ ],
+ "${type}-4": [
+ status: "CANCELLED",
+ key: "${type}-4",
]
]
}
@@ -638,6 +642,104 @@ class ProjectSpec extends SpecHelper {
result == expected
}
+ def "compute wip jira issues for non Gxp project"() {
+ given:
+ def data = [:]
+ Project.JiraDataItem.TYPES_WITH_STATUS.each { type ->
+ data[type] = [
+ "${type}-1": [
+ status: "TODO",
+ key: "${type}-1",
+ ],
+ "${type}-2": [
+ status: "DOING",
+ key: "${type}-2",
+ ],
+ "${type}-3": [
+ status: "DONE",
+ key: "${type}-3",
+ ],
+ "${type}-4": [
+ status: "CANCELLED",
+ key: "${type}-4",
+ ],
+ "${type}-5": [
+ status: Project.JiraDataItem.ISSUE_STATUS_TODO,
+ key: "${type}-5",
+ number: '1',
+ heading: 'Introduction',
+ documents:['SSDS']
+ ],
+ "${type}-6": [
+ status: Project.JiraDataItem.ISSUE_STATUS_DONE,
+ key: "${type}-6",
+ number: '2.1',
+ heading: 'System Design Overview',
+ documents:['SSDS']
+ ],
+ "${type}-7": [
+ status: Project.JiraDataItem.ISSUE_STATUS_CANCELLED,
+ key: "${type}-7",
+ number: '3.1',
+ heading: 'System Design Profile',
+ documents:['SSDS']
+ ],
+ "${type}-8": [
+ status: Project.JiraDataItem.ISSUE_STATUS_TODO,
+ key: "${type}-8",
+ number: '5.4',
+ heading: 'Utilisation of Existing Infrastructure Services',
+ documents:['SSDS']
+ ],
+ "${type}-9": [
+ status: Project.JiraDataItem.ISSUE_STATUS_TODO,
+ key: "${type}-9",
+ number: '1',
+ heading: 'Introduction and Purpose',
+ documents:['SSDS']
+ ],
+ "${type}-10": [
+ status: Project.JiraDataItem.ISSUE_STATUS_TODO,
+ key: "${type}-10",
+ number: '3.1',
+ heading: 'Related Business / GxP Process',
+ documents:['CSD']
+ ],
+ "${type}-11": [
+ status: Project.JiraDataItem.ISSUE_STATUS_TODO,
+ key: "${type}-11",
+ number: '5.1',
+ heading: 'Definitions',
+ documents:['CSD']
+ ],
+ "${type}-12": [
+ status: Project.JiraDataItem.ISSUE_STATUS_TODO,
+ key: "${type}-12",
+ number: '5.2',
+ heading: 'Abbreviations',
+ documents:['CSD']
+ ]
+ ]
+ }
+ project.projectProperties.put(Project.IS_GXP_PROJECT_PROPERTY, 'false')
+ def expected = [:]
+ Project.JiraDataItem.COMMON_TYPES_TO_BE_CLOSED.each { type ->
+ expected[type] = [ "${type}-1", "${type}-2", "${type}-5",
+ "${type}-8", "${type}-9", "${type}-10", "${type}-11", "${type}-12", ]
+ }
+ expected[Project.JiraDataItem.TYPE_DOCS] = [ "${Project.JiraDataItem.TYPE_DOCS}-5",
+ "${Project.JiraDataItem.TYPE_DOCS}-7",
+ "${Project.JiraDataItem.TYPE_DOCS}-8",
+ "${Project.JiraDataItem.TYPE_DOCS}-9",
+ "${Project.JiraDataItem.TYPE_DOCS}-10"]
+
+ when:
+ def result = project.computeWipJiraIssues(data)
+
+ then:
+ result == expected
+ }
+
def "get wip Jira issues for an empty collection"() {
setup:
def data = [project: [:], components: [:]]
@@ -899,6 +1001,132 @@ class ProjectSpec extends SpecHelper {
}
}
+ def "fail build with mandatory doc open issues for non-GxP project"() {
+ setup:
+ def data = [project: [:], components: [:]]
+ Project.JiraDataItem.TYPES_WITH_STATUS.each { type ->
+ data[type] = [
+ "${type}-3": [
+ status: "DONE"
+ ]
+ ]
+ }
+
+ data.project.projectProperties = [:]
+ data.project.projectProperties["PROJECT.IS_GXP"] = "false"
+ data.docs = [:]
+ data.docs["docs-1"] = [ documents: [a], number: b, status: "DOING"]
+ def expected = [:]
+ Project.JiraDataItem.COMMON_TYPES_TO_BE_CLOSED.each { type ->
+ expected[type] = ["${type}-1", "${type}-2"]
+ }
+
+ def expectedMessage = "The pipeline failed since the following issues are work in progress (no documents were generated): "
+
+ expectedMessage += "\n\nDocs: docs-1"
+ project = createProject([
+ "loadJiraData" : {
+ return data
+ },
+ "loadJiraDataBugs": {
+ return [
+ "bugs-3": [
+ status: "DONE"
+ ]
+ ]
+ }
+ ]).init()
+ project.data.buildParams.version = "1.0"
+ when:
+ project.load(git, jiraUseCase)
+
+ then:
+ project.hasWipJiraIssues() == c
+
+ then:
+ def e = thrown(OpenIssuesException)
+ e.message == expectedMessage
+
+ and:
+ Project.JiraDataItem.TYPES_WITH_STATUS.each { type ->
+ !expectedMessage.find("${type}-3")
+ }
+
+ where:
+ a | b || c
+ "CSD" | '1' || true
+ "CSD" | '3.1' || true
+ "SSDS" | '1' || true
+ "SSDS" | '2.1' || true
+ "SSDS" | '3.1' || true
+ "SSDS" | '5.4' || true
+ }
+
+ def "NOT fail build with non-mandatory doc open issues for non-GxP project"() {
+ setup:
+ def data = [project: [:], components: [:]]
+ Project.JiraDataItem.TYPES_WITH_STATUS.each { type ->
+ data[type] = [
+ "${type}-3": [
+ status: "DONE"
+ ]
+ ]
+ }
+
+ data.project.projectProperties = [:]
+ data.project.projectProperties["PROJECT.IS_GXP"] = "false"
+ data.docs = [:]
+ data.docs["docs-1"] = [ documents: [a], number: b, status: "DOING"]
+ def expected = [:]
+ Project.JiraDataItem.COMMON_TYPES_TO_BE_CLOSED.each { type ->
+ expected[type] = ["${type}-1", "${type}-2"]
+ }
+
+ def expectedMessage = "The pipeline failed since the following issues are work in progress (no documents were generated): "
+
+ expectedMessage += "\n\nDocs: docs-1"
+ project = createProject([
+ "loadJiraData" : {
+ return data
+ },
+ "loadJiraDataBugs": {
+ return [
+ "bugs-3": [
+ status: "DONE"
+ ]
+ ]
+ }
+ ]).init()
+ project.data.buildParams.version = "1.0"
+ when:
+ project.load(git, jiraUseCase)
+
+ then:
+ project.hasWipJiraIssues() == c
+
+ where:
+ a | b || c
+ "CSD" | '2' || false
+ "CSD" | '3.2' || false
+ "SSDS" | '2' || false
+ "SSDS" | '2.2' || false
+ "SSDS" | '3.2' || false
+ "SSDS" | '5.5' || false
+ "CFTP" | '1' || false
+ "CFTR" | '1' || false
+ "DTP" | '1' || false
+ "DTR" | '1' || false
+ "DIL" | '1' || false
+ "IVP" | '1' || false
+ "IVR" | '1' || false
+ "RA" | '1' || false
+ "TCP" | '1' || false
+ "TCR" | '1' || false
+ "TIP" | '1' || false
+ "TIR" | '1' || false
+ "TRC" | '1' || false
+ }
+
def "load initial version"() {
given:
def component1 = [key: "CMP-1", name: "Component 1"]
@@ -2703,6 +2931,110 @@ class ProjectSpec extends SpecHelper {
result == expected
}
+ def "compute WIP document chapters per document for non Gxp docs - all mandatory issues done"() {
+ given:
+ def issue = { String key, String number, String heading, String status,
+ List docs -> [(key): [ documents: docs, status: status, key: key, number: number, heading: heading ]]
+ }
+
+ def data = [
+ (Project.JiraDataItem.TYPE_DOCS): issue('77', '1', 'Introduction',
+ Project.JiraDataItem.ISSUE_STATUS_DONE, ['SSDS']) +
+ issue('76', '2.1', 'System Design Overview',
+ Project.JiraDataItem.ISSUE_STATUS_DONE, ['SSDS']) +
+ issue('73', '3.1', 'System Design Profile',
+ Project.JiraDataItem.ISSUE_STATUS_DONE, ['SSDS']) +
+ issue('67', '5.4', 'Utilisation of Existing Infrastructure Services',
+ Project.JiraDataItem.ISSUE_STATUS_DONE, ['SSDS']) +
+ issue('66', '6.1', 'Development Environment',
+ Project.JiraDataItem.ISSUE_STATUS_TODO, ['SSDS']) +
+ issue('42', '1', 'Introduction and Purpose',
+ Project.JiraDataItem.ISSUE_STATUS_DONE, ['CSD']) +
+ issue('40', '3.1', 'Related Business / GxP Process',
+ Project.JiraDataItem.ISSUE_STATUS_DONE, ['CSD']) +
+ issue('39', '5.1', 'Definitions',
+ Project.JiraDataItem.ISSUE_STATUS_TODO, ['CSD']) +
+ issue('38', '5.2', 'Abbreviations',
+ Project.JiraDataItem.ISSUE_STATUS_TODO, ['CSD'])
+ ]
+ project.projectProperties.put(Project.IS_GXP_PROJECT_PROPERTY, 'false')
+ def expected = [:]
+
+ when:
+ def result = project.computeWipDocChapterPerDocument(data)
+
+ then:
+ result == expected
+ }
+
+ def "compute WIP document chapters per document for non Gxp docs - one mandatory issue to do and one cancelled"() {
+ given:
+ def issue = { String key, String number, String heading, String status,
+ List docs -> [(key): [ documents: docs, status: status, key: key, number: number, heading: heading ]]
+ }
+
+ def data = [
+ (Project.JiraDataItem.TYPE_DOCS): issue('77', '1', 'Introduction',
+ Project.JiraDataItem.ISSUE_STATUS_TODO, ['SSDS']) +
+ issue('76', '2.1', 'System Design Overview',
+ Project.JiraDataItem.ISSUE_STATUS_CANCELLED, ['SSDS']) +
+ issue('73', '3.1', 'System Design Profile',
+ Project.JiraDataItem.ISSUE_STATUS_DONE, ['SSDS']) +
+ issue('67', '5.4', 'Utilisation of Existing Infrastructure Services',
+ Project.JiraDataItem.ISSUE_STATUS_DONE, ['SSDS']) +
+ issue('42', '1', 'Introduction and Purpose',
+ Project.JiraDataItem.ISSUE_STATUS_DONE, ['CSD']) +
+ issue('40', '3.1', 'Related Business / GxP Process',
+ Project.JiraDataItem.ISSUE_STATUS_DONE, ['CSD']) +
+ issue('39', '5.1', 'Definitions',
+ Project.JiraDataItem.ISSUE_STATUS_TODO, ['CSD']) +
+ issue('38', '5.2', 'Abbreviations',
+ Project.JiraDataItem.ISSUE_STATUS_TODO, ['CSD'])
+ ]
+ project.projectProperties.put(Project.IS_GXP_PROJECT_PROPERTY, 'false')
+ def expected = [SSDS:['77', '76']]
+
+ when:
+ def result = project.computeWipDocChapterPerDocument(data)
+
+ then:
+ result == expected
+ }
+
+ def "compute WIP document chapters per document for non Gxp docs - all issues to do"() {
+ given:
+ def issue = { String key, String number, String heading, String status,
+ List docs -> [(key): [ documents: docs, status: status, key: key, number: number, heading: heading ]]
+ }
+
+ def data = [
+ (Project.JiraDataItem.TYPE_DOCS): issue('77', '1', 'Introduction',
+ Project.JiraDataItem.ISSUE_STATUS_TODO, ['SSDS']) +
+ issue('76', '2.1', 'System Design Overview',
+ Project.JiraDataItem.ISSUE_STATUS_TODO, ['SSDS']) +
+ issue('73', '3.1', 'System Design Profile',
+ Project.JiraDataItem.ISSUE_STATUS_TODO, ['SSDS']) +
+ issue('67', '5.4', 'Utilisation of Existing Infrastructure Services',
+ Project.JiraDataItem.ISSUE_STATUS_TODO, ['SSDS']) +
+ issue('42', '1', 'Introduction and Purpose',
+ Project.JiraDataItem.ISSUE_STATUS_TODO, ['CSD']) +
+ issue('40', '3.1', 'Related Business / GxP Process',
+ Project.JiraDataItem.ISSUE_STATUS_TODO, ['CSD']) +
+ issue('39', '5.1', 'Definitions',
+ Project.JiraDataItem.ISSUE_STATUS_DONE, ['CSD']) +
+ issue('38', '5.2', 'Abbreviations',
+ Project.JiraDataItem.ISSUE_STATUS_DONE, ['CSD'])
+ ]
+ project.projectProperties.put(Project.IS_GXP_PROJECT_PROPERTY, 'false')
+ def expected = [SSDS:['77', '76', '73', '67'], CSD:['42', '40']]
+
+ when:
+ def result = project.computeWipDocChapterPerDocument(data)
+
+ then:
+ result == expected
+ }
+
def "assert if versioning is enabled for the project"() {
given:
def versionEnabled
@@ -2853,4 +3185,36 @@ class ProjectSpec extends SpecHelper {
"FALSE" || false
}
+ def "verify isGxpProject default value"() {
+ given:
+ project.projectProperties.remove(Project.IS_GXP_PROJECT_PROPERTY)
+
+ when:
+ def result = project.isGxpProject()
+
+ then:
+ result == Project.IS_GXP_PROJECT_DEFAULT
+ }
+
+ def "verify isGxpProject true value"() {
+ given:
+ project.projectProperties.put(Project.IS_GXP_PROJECT_PROPERTY, 'true')
+
+ when:
+ def result = project.isGxpProject()
+
+ then:
+ result == true
+ }
+
+ def "verify isGxpProject false value"() {
+ given:
+ project.projectProperties.put(Project.IS_GXP_PROJECT_PROPERTY, 'false')
+
+ when:
+ def result = project.isGxpProject()
+
+ then:
+ result == false
+ }
}
diff --git a/test/resources/project-jira-data.json b/test/resources/project-jira-data.json
index 874056ffc6..6f6dd0d7cb 100644
--- a/test/resources/project-jira-data.json
+++ b/test/resources/project-jira-data.json
@@ -26,7 +26,8 @@
"PROJECT.POO_CAT.HIGH": "Frequency of the usage of the related function is >10 times per week.",
"PROJECT.POO_CAT.LOW": "Frequency of the usage of the related function is <10 times per year.",
"PROJECT.POO_CAT.MEDIUM": "Frequency of the usage of the related function is <10 times per week.",
- "PROJECT.USES_POO": "true"
+ "PROJECT.USES_POO": "true",
+ "PROJECT.IS_GXP": "true"
},
"enumDictionary": {
"ProbabilityOfDetection": {