diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 5350178..7c29335 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -1,12 +1,8 @@
-# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
----
+# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
+
version: 2
updates:
- - package-ecosystem: "maven"
- directory: "/"
+ - package-ecosystem: github-actions
+ directory: /
schedule:
- interval: "weekly"
- - package-ecosystem: "github-actions"
- directory: "/"
- schedule:
- interval: "weekly"
\ No newline at end of file
+ interval: monthly
\ No newline at end of file
diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml
index 4ec641f..4ed532e 100644
--- a/.github/release-drafter.yml
+++ b/.github/release-drafter.yml
@@ -1,3 +1,2 @@
# https://github.com/jenkinsci/.github/blob/master/.github/release-drafter.adoc
-_extends: .github
-tag-template: zdevops-$NEXT_MINOR_VERSION
\ No newline at end of file
+_extends: .github
\ No newline at end of file
diff --git a/.github/workflows/cd.yaml b/.github/workflows/cd.yaml
new file mode 100644
index 0000000..64a6693
--- /dev/null
+++ b/.github/workflows/cd.yaml
@@ -0,0 +1,15 @@
+# Note: additional setup is required, see https://www.jenkins.io/redirect/continuous-delivery-of-plugins
+
+name: cd
+on:
+ workflow_dispatch:
+ check_run:
+ types:
+ - completed
+
+jobs:
+ maven-cd:
+ uses: jenkins-infra/github-reusable-workflows/.github/workflows/maven-cd.yml@v1
+ secrets:
+ MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
+ MAVEN_TOKEN: ${{ secrets.MAVEN_TOKEN }}
\ No newline at end of file
diff --git a/.github/workflows/jenkins-security-scan.yml b/.github/workflows/jenkins-security-scan.yml
new file mode 100644
index 0000000..6fc0b2b
--- /dev/null
+++ b/.github/workflows/jenkins-security-scan.yml
@@ -0,0 +1,21 @@
+name: Jenkins Security Scan
+
+on:
+ push:
+ branches:
+ - main
+ pull_request:
+ types: [ opened, synchronize, reopened ]
+ workflow_dispatch:
+
+permissions:
+ security-events: write
+ contents: read
+ actions: read
+
+jobs:
+ security-scan:
+ uses: jenkins-infra/jenkins-security-scan/.github/workflows/jenkins-security-scan.yaml@v2
+ with:
+ java-cache: 'maven' # Optionally enable use of a build dependency cache. Specify 'maven' or 'gradle' as appropriate.
+ # java-version: 21 # Optionally specify what version of Java to set up for the build, or remove to use a recent default.
diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml
deleted file mode 100644
index 281fade..0000000
--- a/.github/workflows/release-drafter.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-# Note: additional setup is required, see https://github.com/jenkinsci/.github/blob/master/.github/release-drafter.adoc
-
-name: Release Drafter
-
-on:
- push:
- branches:
- - "main"
-
-jobs:
- update_release_draft:
- runs-on: ubuntu-latest
- steps:
- # Drafts your next Release notes as Pull Requests are merged into the default branch
- - uses: release-drafter/release-drafter@v5
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
diff --git a/.mvn/extensions.xml b/.mvn/extensions.xml
index 80a2e47..34fc756 100644
--- a/.mvn/extensions.xml
+++ b/.mvn/extensions.xml
@@ -2,6 +2,6 @@
io.jenkins.tools.incrementals
git-changelist-maven-extension
- 1.6
+ 1.8
\ No newline at end of file
diff --git a/.mvn/maven.config b/.mvn/maven.config
index 2582cab..61cf4e5 100644
--- a/.mvn/maven.config
+++ b/.mvn/maven.config
@@ -1,3 +1,3 @@
-Pconsume-incrementals
-Pmight-produce-incrementals
--DaltDeploymentRepository=maven.jenkins-ci.org::default::https://repo.jenkins-ci.org/releases/
\ No newline at end of file
+-Dchangelist.format=%d.v%s
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 91ab51b..b967071 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -21,6 +21,7 @@ All notable changes to the Zowe zDevOps Jenkins Plugin will be documented in thi
* Feature: Added Jenkins Freestyle UI method - "Write text to member" ([4e4d73cc](https://github.com/zowe/zowe-zdevops-jenkins-plugin/commit/4e4d73cc))
* Feature: Added dataset member name validation ([b05c7436](https://github.com/zowe/zowe-zdevops-jenkins-plugin/commit/b05c7436))
* Feature: Added hpi-builder.yml GitHub workflow for automated .hpi builds ([c0fd9f27](https://github.com/zowe/zowe-zdevops-jenkins-plugin/commit/c0fd9f27))
+* Feature: Added failOnExist parameter for allocateDS, deleteDataset and deleteDatasetsByMask declarative/Freestyle UI methods (checks the presence/absence of a dataset on the system) ([db232f49](https://github.com/zowe/zowe-zdevops-jenkins-plugin/commit/db232f49))
### Bugfixes
diff --git a/Jenkinsfile b/Jenkinsfile
index 12f6a8d..da6f699 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -8,4 +8,4 @@
* Copyright IBA Group 2022
*/
-buildPlugin(useContainerAgent: true, tests: [[skip: 'true']], configurations: [[ platform: 'linux', jdk: '17' ]])
+buildPlugin(useContainerAgent: true, configurations: [[ platform: 'linux', jdk: '17' ]])
diff --git a/README.md b/README.md
index 2ff73de..4e6173d 100644
--- a/README.md
+++ b/README.md
@@ -27,7 +27,7 @@ Thank you for considering IBA Group for your mainframe needs.
## Before use - Plugin configuration
After successfully installing the plugin, you need to configure it for further work - this will require a minimum of actions.
-1. Move to “Manage Jenkins” -> “Configure System / System” -> scroll to the very bottom of the list of installed plugins and find the panel with the name - “z/OS Connection List”
+1. Move to 'Manage Jenkins' -> 'Configure System / System' -> scroll to the very bottom of the list of installed plugins and find the panel with the name - 'z/OS Connection List'
2. This setting allows you to add all necessary z/OS systems and configure access to them.
It is necessary to set the connection name (it is also the ID for declarative methods in the code). For the example: ```z/os-connection-name```
3. The URL address and port of the required mainframe to connect via z/OSMF. Example: ```https://:```
@@ -45,7 +45,7 @@ stage ("stage-name") {
submitJobSync "//'EXAMPLE.DATASET(MEMBER)'"
downloadDS "EXAMPLE.DATASET(MEMBER)"
downloadDS dsn:"EXAMPLE.DATASET(MEMBER)", vol:"VOL001"
- allocateDS dsn:"EXAMPLE.DATASET", alcUnit:"TRK", dsOrg:"PS", primary:1, secondary:1, recFm:"FB"
+ allocateDS dsn:"EXAMPLE.DATASET", alcUnit:"TRK", dsOrg:"PS", primary:1, secondary:1, recFm:"FB", failOnExist:"False"
writeFileToDS dsn:"EXAMPLE.DATASET", file:"workspaceFile"
writeFileToDS dsn:"EXAMPLE.DATASET", file:"D:\\files\\localFile"
writeToDS dsn:"EXAMPLE.DATASET", text:"Write this string to dataset"
@@ -57,9 +57,9 @@ stage ("stage-name") {
writeFileToFile destFile: "u/USER/myfile", sourceFile: "myfile.txt"
writeFileToFile destFile: "u/USER/myfile", sourceFile: "myfile.txt", binary: "true"
- deleteDataset dsn:"EXAMPLE.DATASET"
- deleteDataset dsn:"EXAMPLE.DATASET", member:"MEMBER"
- deleteDatasetsByMask mask:"EXAMPLE.DATASET.*"
+ deleteDataset dsn:"EXAMPLE.DATASET", failOnNotExist:"False"
+ deleteDataset dsn:"EXAMPLE.DATASET", member:"MEMBER", failOnNotExist:"True"
+ deleteDatasetsByMask mask:"EXAMPLE.DATASET.*", failOnNotExist:"False"
}
// ...
}
@@ -70,7 +70,30 @@ stage ("stage-name") {
### allocateDS - Represents an action for allocating a dataset in a declarative style
```groovy
-allocateDS dsn:"EXAMPLE.DATASET", dsOrg:"PS", primary:1, secondary:1, recFm:"FB"
+zosmf ("z/os-connection-name") {
+ allocateDS(
+ // Mandatory Parameters below:
+ dsn: "EXAMPLE.DATASET",
+ dsOrg: "PS",
+ primary: 1,
+ secondary: 1,
+ recFm: "FB",
+ failOnExist:"False",
+ // Optional Parameters below:
+ volser:"YOURVOL",
+ unit:"SYSDA",
+ alcUnit:"TRK",
+ dirBlk:"5",
+ blkSize:"800",
+ lrecl:"80",
+ storClass:"STORAGECLASS",
+ mgntClass:"MGMTCLASS",
+ dataClass:"DATACLASS",
+ avgBlk:"10",
+ dsnType:"LIBRARY",
+ dsModel:"MODEL.DATASET.NAME"
+ )
+}
```
**Mandatory Parameters:**
* ```dsn:"EXAMPLE.DATASET"``` - The name of the dataset to be allocated
@@ -78,6 +101,7 @@ allocateDS dsn:"EXAMPLE.DATASET", dsOrg:"PS", primary:1, secondary:1, recFm:"FB"
* ```primary:"1"``` - The primary allocation size in cylinders or tracks
* ```secondary:"1"``` - The secondary allocation size in cylinders or tracks
* ```recFm:"FB"``` - The record format (could be only F, FB, V, VB, U, VSAM, VA)
+ * ```failOnExist:"False"``` - If the dataset already exists and the option is enabled, execution will halt. (Boolean parameter, is set to 'False' by default)
**Optional parms:**
* ```volser:"YOURVOL"``` - Volume serial number where the dataset will be allocated.
@@ -96,17 +120,20 @@ allocateDS dsn:"EXAMPLE.DATASET", dsOrg:"PS", primary:1, secondary:1, recFm:"FB"
### deleteDataset - Represents an action for deleting datasets and members in a declarative style
```groovy
-deleteDataset dsn:"EXAMPLE.DATASET"
+zosmf ("z/os-connection-name") {
+ deleteDataset dsn: "EXAMPLE.DATASET", member:"MEMBER", failOnNotExist:"False"
+}
```
**Mandatory Parameters:**
* ```dsn:"EXAMPLE.DATASET"``` - Sequential or library dataset name for deletion
* ```member:"MEMBER"``` - Dataset member name for deletion
+ * ```failOnNotExist:"False"``` - If the dataset has been deleted and the option is enabled, execution will halt. (Boolean parameter, is set to 'False' by default)
**Expected behavior under various deletion scenarios:**
* To delete a member from the library, the dsn and member parameters must be specified:
```
- deleteDataset dsn:"EXAMPLE.DATASET", member:"MEMBER"
+ deleteDataset dsn:"EXAMPLE.DATASET", member:"MEMBER", failOnNotExist:"False"
```
* You cannot delete a VSAM dataset this way. Otherwise, you will get output similar to:
@@ -176,7 +203,7 @@ Pipeline can be used either directly inside the ```Pipeline``` code block in the
This pipeline example uses all currently available methods and functionality of the Zowe zDevOps plugin.
**Steps to Execute the Pipeline:**
-1. Add a zosmf connection in settings (“Manage Jenkins” -> “Configure System / System” -> z/OS Connection List). Enter a connection name, zosmf url, username and password.
+1. Add a zosmf connection in settings ('Manage Jenkins' -> 'Configure System / System' -> z/OS Connection List). Enter a connection name, zosmf url, username and password.
2. Create a new Jenkins item -> ```Pipeline``` and open its configuration.
3. In the ```Pipeline``` section, paste the code from the example below and replace all the necessary variables with your data
4. Done, enjoy the minimal ready-made pipeline template!
@@ -217,9 +244,9 @@ pipeline {
stage('Allocate DSs') {
steps {
zosmf("${ZOS_CONN_ID}") {
- allocateDS dsn:"${PS_DATASET_1}", dsOrg:"PS", primary:1, secondary:1, recFm:"FB"
- allocateDS dsn:"${PS_DATASET_2}", dsOrg:"PS", primary:1, secondary:1, recFm:"FB", alcUnit:"TRK"
- allocateDS dsn:"${PO_DATASET}(${PO_MEMBER})", dsOrg:"PO", primary:1, secondary:1, recFm:"FB"
+ allocateDS dsn:"${PS_DATASET_1}", dsOrg:"PS", primary:1, secondary:1, recFm:"FB", failOnExist:"False"
+ allocateDS dsn:"${PS_DATASET_2}", dsOrg:"PS", primary:1, secondary:1, recFm:"FB", alcUnit:"TRK", failOnExist:"False"
+ allocateDS dsn:"${PO_DATASET}(${PO_MEMBER})", dsOrg:"PO", primary:1, secondary:1, recFm:"FB", failOnExist:"False"
}
}
}
@@ -270,8 +297,8 @@ pipeline {
stage('Clean up') {
steps {
zosmf("${ZOS_CONN_ID}") {
- deleteDataset dsn:"${PS_DATASET_1}"
- deleteDatasetsByMask mask:"${HLQ}.NEW.*"
+ deleteDataset dsn:"${PS_DATASET_1}", failOnNotExist:"False"
+ deleteDatasetsByMask mask:"${HLQ}.NEW.*", failOnNotExist:"True"
}
}
}
@@ -321,7 +348,7 @@ The plugin are packaged as self-contained .hpi files, which have all the
### [Zowe zDevOps plugin installation .hpi file](https://github.com/IBA-mainframe-dev/Global-Repository-for-Mainframe-Developers/blob/master/Jenkins%20zOS%20DevOps%20plugin%20installable%20hpi/zos-devops.hpi)
Assuming a .hpi file has been downloaded, a logged-in Jenkins administrator may upload the file from within the web UI:
-1. Navigate to the Manage Jenkins > Manage Plugins page in the web UI.
+1. Navigate to the Manage Jenkins > Plugins page in the web UI.
2. Click on the Advanced tab.
3. Choose the .hpi file from your system or enter a URL to the archive file under the Deploy Plugin section.
4. Deploy the plugin file.
@@ -332,8 +359,8 @@ Assuming a .hpi file has been downloaded, a logged-in Jenkins administrat
3. To generate the ```target``` dir with generated-sources - you have to run the Maven command: ```mvn localizer:generate```
4. Next, you need to generate an installation file: .hpi or .jpi file (both are installation files for the Jenkins plugin). This can be done by executing Maven command ```mvn install``` or by ```mvn hpi:hpi```.
5. After building the .hpi/.jpi file, it should appear in a /build/libs/.hpi directory
-6. Next you need to login into the Jenkins, move to the “Manage Jenkins” -> “Manage Plugins” -> “Advanced (tab)” -> “Deploy Plugin” (You can select a plugin file from your local system or provide a URL to install a plugin from outside the central plugin repository) -> Specify the path to the generated .hpi/.jpi file (or by dragging the file from Intellij IDEA project to the file upload field in the Jenkins).
-7. Click “Deploy”, reboot Jenkins after installation. The Plugin is ready to go!
+6. Next you need to login into the Jenkins, move to the 'Manage Jenkins' -> 'Plugins' -> 'Advanced settings (tab)' -> 'Deploy Plugin' (You can select a plugin file from your local system or provide a URL to install a plugin from outside the central plugin repository) -> Specify the path to the generated .hpi/.jpi file (or by dragging the file from Intellij IDEA project to the file upload field in the Jenkins).
+7. Click 'Deploy', reboot Jenkins after installation. The Plugin is ready to go!
## How to run Jenkins plugin in Debug mode in a local Jenkins sandbox
diff --git a/pom.xml b/pom.xml
index 7471310..463a31d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -8,26 +8,25 @@
- org.zowe
+ io.jenkins.plugins
zdevops
- ${revision}${changelist}
+ ${revision}.${changelist}
Zowe zDevOps
hpi
Zowe mainframe z/OS automation plugin, working through z/OSMF REST API and using Zowe Kotlin SDK
https://github.com/jenkinsci/${project.artifactId}-plugin
-
- 0.3.0
- -SNAPSHOT
+ 1.2.0
+ 999999-SNAPSHOT
2.414.3
17
1.9.20
true
1.13
4.10.0
- 0.5.0-rc.11
+ 0.5.0
5.6.1
official
17
@@ -62,8 +61,8 @@
- scm:git:https://github.com/${gitHubRepo}.git
- scm:git:git@github.com:${gitHubRepo}.git
+ scm:git:https://github.com/${gitHubRepo}
+ scm:git:https://github.com/${gitHubRepo}
https://github.com/${gitHubRepo}
${scmTag}
@@ -336,7 +335,7 @@
org.yaml
snakeyaml
- 2.2
+ 2.3
@@ -372,7 +371,13 @@
com.google.code.gson
gson
- 2.10.1
+ 2.11.0
+
+
+
+ com.google.errorprone
+ error_prone_annotations
+ 2.27.0
@@ -460,7 +465,8 @@
- zowe.jfrog.io
+
+ org.zowe.sdk
https://zowe.jfrog.io/artifactory/libs-release
diff --git a/src/main/kotlin/org/zowe/zdevops/classic/files/dsn/DownloadDatasetStep.kt b/src/main/kotlin/org/zowe/zdevops/classic/files/dsn/DownloadDatasetStep.kt
index db7e98e..98e9579 100644
--- a/src/main/kotlin/org/zowe/zdevops/classic/files/dsn/DownloadDatasetStep.kt
+++ b/src/main/kotlin/org/zowe/zdevops/classic/files/dsn/DownloadDatasetStep.kt
@@ -1,11 +1,15 @@
/*
+ * Copyright (c) 2023-2024 IBA Group.
+ *
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
- * Copyright IBA Group 2023
+ * Contributors:
+ * IBA Group
+ * Zowe Community
*/
package org.zowe.zdevops.classic.files.dsn
@@ -70,7 +74,8 @@ constructor(
zosConnection: ZOSConnection
) {
val workspace = build.executor?.currentWorkspace!!
- downloadDSOrDSMemberByType(dsn, vol, returnEtag, listener, zosConnection, workspace)
+ val jenkinsJobUrl = build.getEnvironment(listener)["JOB_URL"]
+ downloadDSOrDSMemberByType(dsn, vol, returnEtag, listener, zosConnection, workspace, jenkinsJobUrl)
}
diff --git a/src/main/kotlin/org/zowe/zdevops/declarative/files/dsn/DownloadFileDeclarative.kt b/src/main/kotlin/org/zowe/zdevops/declarative/files/dsn/DownloadFileDeclarative.kt
index 108df17..2710ec7 100644
--- a/src/main/kotlin/org/zowe/zdevops/declarative/files/dsn/DownloadFileDeclarative.kt
+++ b/src/main/kotlin/org/zowe/zdevops/declarative/files/dsn/DownloadFileDeclarative.kt
@@ -1,11 +1,15 @@
/*
+ * Copyright (c) 2022-2024 IBA Group.
+ *
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
- * Copyright IBA Group 2022
+ * Contributors:
+ * IBA Group
+ * Zowe Community
*/
package org.zowe.zdevops.declarative.files.dsn
@@ -51,7 +55,8 @@ class DownloadFileDeclarative @DataBoundConstructor constructor(val dsn: String)
zosConnection: ZOSConnection
) {
val workspacePath = FilePath(null, workspace.remote.replace(workspace.name,""))
- downloadDSOrDSMemberByType(dsn, vol, returnEtag, listener, zosConnection, workspacePath)
+ val jenkinsJobUrl = env["BUILD_URL"] + "/execution/node/3/"
+ downloadDSOrDSMemberByType(dsn, vol, returnEtag, listener, zosConnection, workspacePath, jenkinsJobUrl)
}
diff --git a/src/main/kotlin/org/zowe/zdevops/logic/DownloadOperation.kt b/src/main/kotlin/org/zowe/zdevops/logic/DownloadOperation.kt
index 69edb90..e82a05a 100644
--- a/src/main/kotlin/org/zowe/zdevops/logic/DownloadOperation.kt
+++ b/src/main/kotlin/org/zowe/zdevops/logic/DownloadOperation.kt
@@ -1,17 +1,22 @@
/*
+ * Copyright (c) 2023-2024 IBA Group.
+ *
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* SPDX-License-Identifier: EPL-2.0
*
- * Copyright IBA Group 2023
+ * Contributors:
+ * IBA Group
+ * Zowe Community
*/
package org.zowe.zdevops.logic
import hudson.AbortException
import hudson.FilePath
+import hudson.console.HyperlinkNote
import hudson.model.TaskListener
import org.apache.commons.io.IOUtils
import org.zowe.kotlinsdk.DatasetOrganization
@@ -24,7 +29,8 @@ import org.zowe.zdevops.Messages
import java.io.File
import java.io.InputStream
import java.io.StringWriter
-
+import java.net.URLEncoder
+import java.nio.charset.StandardCharsets
/**
@@ -36,6 +42,7 @@ import java.io.StringWriter
* @param zosConnection The connection to the z/OS system.
* @param workspace The workspace where the dataset will be downloaded.
* @param listener The listener for capturing task progress and logs.
+ * @param jenkinsJobUrl The job/pipeline URL
*/
fun downloadDS(
dsn: String,
@@ -43,7 +50,8 @@ fun downloadDS(
returnEtag: Boolean?,
zosConnection: ZOSConnection,
workspace: FilePath,
- listener: TaskListener
+ listener: TaskListener,
+ jenkinsJobUrl: String?,
) {
var downloadedDSN: InputStream?
try {
@@ -55,7 +63,9 @@ fun downloadDS(
IOUtils.copy(downloadedDSN, writer, "UTF-8")
val file = File("$workspace\\$dsn")
file.writeText(writer.toString())
- listener.logger.println(Messages.zdevops_declarative_DSN_downloaded_success(dsn))
+ val urlEncodedDsn = URLEncoder.encode(dsn, StandardCharsets.UTF_8.toString())
+ listener.logger.println(Messages.zdevops_declarative_DSN_downloaded_success(
+ HyperlinkNote.encodeTo("${jenkinsJobUrl}ws/$urlEncodedDsn/*view*/", dsn)))
}
/**
@@ -67,6 +77,7 @@ fun downloadDS(
* @param listener The listener for capturing task progress and logs.
* @param zosConnection The connection to the z/OS system.
* @param workspace The workspace where the dataset will be downloaded.
+ * @param jenkinsJobUrl The job/pipeline URL
*/
fun downloadDSOrDSMemberByType(
dsn: String,
@@ -74,23 +85,24 @@ fun downloadDSOrDSMemberByType(
returnEtag: Boolean?,
listener: TaskListener,
zosConnection: ZOSConnection,
- workspace: FilePath
+ workspace: FilePath,
+ jenkinsJobUrl: String?
) {
listener.logger.println(Messages.zdevops_declarative_DSN_downloading(dsn, vol, zosConnection.host, zosConnection.zosmfPort))
val dsnMemberPattern = Regex("[\\w#\$@.-]{1,}\\([\\w#\$@]{1,8}\\)") //means it's a PDS member
if (dsn.contains(dsnMemberPattern)) {
- downloadDS(dsn, vol, returnEtag, zosConnection, workspace, listener)
+ downloadDS(dsn, vol, returnEtag, zosConnection, workspace, listener, jenkinsJobUrl)
} else {
val dsnList = ZosDsnList(zosConnection).listDsn(dsn, ListParams(vol))
if (dsnList.items.isEmpty()) {
throw AbortException("Can't find $dsn ${ if(vol.isNullOrBlank()) "" else "on volume $vol"}")
}
when (dsnList.items.first().datasetOrganization) {
- DatasetOrganization.PS -> downloadDS(dsn, vol, returnEtag, zosConnection, workspace, listener)
+ DatasetOrganization.PS -> downloadDS(dsn, vol, returnEtag, zosConnection, workspace, listener, jenkinsJobUrl)
DatasetOrganization.PO, DatasetOrganization.POE -> {
listener.logger.println(Messages.zdevops_declarative_DSN_downloading_members(dsn))
ZosDsnList(zosConnection).listDsnMembers(dsn, ListParams(vol)).items.forEach {
- downloadDS("${dsn}(${it.name})", vol, returnEtag, zosConnection, workspace, listener)
+ downloadDS("${dsn}(${it.name})", vol, returnEtag, zosConnection, workspace, listener, jenkinsJobUrl)
}
}
else -> listener.logger.println(Messages.zdevops_declarative_DSN_downloading_invalid_dsorg())
diff --git a/src/main/kotlin/org/zowe/zdevops/logic/SubmitJobOperation.kt b/src/main/kotlin/org/zowe/zdevops/logic/SubmitJobOperation.kt
index 8fd19bd..0586d1c 100644
--- a/src/main/kotlin/org/zowe/zdevops/logic/SubmitJobOperation.kt
+++ b/src/main/kotlin/org/zowe/zdevops/logic/SubmitJobOperation.kt
@@ -25,6 +25,8 @@ import org.zowe.zdevops.Messages
import org.zowe.zdevops.utils.extractSubmitJobMessage
import org.zowe.zdevops.utils.runMFTryCatchWrappedQuery
import java.io.File
+import java.net.URLEncoder
+import java.nio.charset.StandardCharsets
/**
* Submits a z/OS job
@@ -93,10 +95,11 @@ fun submitJobSync(
val logPath = "$workspacePath/${finalResult.jobName}.${finalResult.jobId}"
val file = File(logPath)
file.writeText(fullLog)
+ val urlEncodedJobName = URLEncoder.encode(finalResult.jobName, StandardCharsets.UTF_8.toString())
listener.logger.println(Messages.zdevops_declarative_ZOSJobs_got_log(
HyperlinkNote.encodeTo(
linkBuilder(buildUrl, finalResult.jobName, finalResult.jobId),
- "${finalResult.jobName}.${finalResult.jobId}"
+ "$urlEncodedJobName.${finalResult.jobId}"
)
))
} else {
diff --git a/src/test/kotlin/org/zowe/zdevops/classic/files/dsn/DownloadDatasetStepSpec.kt b/src/test/kotlin/org/zowe/zdevops/classic/files/dsn/DownloadDatasetStepSpec.kt
index 4269fe6..4f421cf 100644
--- a/src/test/kotlin/org/zowe/zdevops/classic/files/dsn/DownloadDatasetStepSpec.kt
+++ b/src/test/kotlin/org/zowe/zdevops/classic/files/dsn/DownloadDatasetStepSpec.kt
@@ -11,9 +11,11 @@
package org.zowe.zdevops.classic.files.dsn
import hudson.AbortException
+import hudson.EnvVars
import hudson.FilePath
import hudson.model.Executor
import hudson.model.Item
+import hudson.model.TaskListener
import hudson.util.FormValidation
import io.kotest.assertions.assertSoftly
import io.kotest.assertions.fail
@@ -70,6 +72,12 @@ class DownloadDatasetStepSpec : ShouldSpec({
every { mockInstance.currentWorkspace } returns FilePath(virtualChannel, mockDir.absolutePath)
return mockInstance
}
+
+ override fun getEnvironment(log: TaskListener): EnvVars {
+ val env = EnvVars()
+ env["JOB_URL"] = "TEST"
+ return env
+ }
}
afterEach {