I am migrating my code from Jenkins to GitHub Actions. My code in Jenkins is already in Production.
What does my pipeline do?
Reads Config.json
file that is on GitHub.
In the Script, it initializes all variables, arrays, objects based on the values from Config.json
.
Fires series of cURL commands based on the conditions.
What I intend to do?
Instead of reinventing the wheel for the GitHub Actions, I want to reuse the script {}
code from Jenkins in the GitHub Actions by executing script.groovy
from migrateToGitHubActions.yaml
.
script.groovy
has the exact code of script {}
from Jenkins pipeline.
From my Jenkins:
pipeline{
agent any
stages{
stage('Start'){
steps{
sh 'ls'
}
}
stage('Clone Repo'){
steps{
git credentialsId: 'githubapp', url: 'https://github.com/configurations.git', branch: "${env}"
}
}
stage('Configure'){
steps{
script{
sh 'cat Config.json'
def configs = readJSON(file: 'Config.json')
def totalBundles = configs.bundles.size()
println "Total Array Size =" + totalBundles
def productName = new Object[totalBundles]
....
}
}
}
}
}
Config.json:
{
"bundles":
[
{
"product":{
"name" : "Product1",
"proxies" : ["'Proxy1', 'Proxy2'"],
"attributes" : [{"name":"Test1","value":"abc"}]
},
"app":{
"name":"App1",
"attributes": [{"name": "attribute1","value": "null"}],
"developer": "[email protected]"
}
},
{
"product":{
"name" : "Product2",
"proxies" : ["'Proxy1', 'Proxy2'"],
"attributes" : [{"name":"Test2","value":"xyz"}]
},
"app":{
"name":"App1",
"attributes": [{"name": "attribute2","value": "null"}],
"developer": "[email protected]"
}
}
]
}
My GitHub Actions migrateToGitHubActions.yaml:
name: Config
on:
workflow_dispatch:
jobs:
build:
runs-on: [abc]
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: List files (Start)
run: |
ls
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'adopt'
- name: Install Groovy
run: sudo apt-get update && sudo apt-get install -y groovy
- name: Run Groovy script
run: groovy script.groovy
script.groovy:
#!/usr/bin/env groovy
import groovy.json.JsonSlurper
println "*** Before Read ***"
// Reading JSON from file
def jsonFile = new File('AppsProductsConfig.json')
def configs = new JsonSlurper().parseText(jsonFile.text)
println "configs = $configs"
println "*** After Read ***"
def totalBundles = configs.bundles.size()
println "Total Array Size = $totalBundles"
// Initialization of arrays
def productName = new String[totalBundles]
def developer = new String[totalBundles]
def firstName = new String[totalBundles]
def lastName = new String[totalBundles]
def userName = new String[totalBundles]
def approvalType = new String[totalBundles]
def productAttributeName = new String[totalBundles]
def productAttributeValue = new String[totalBundles]
def displayName = new String[totalBundles]
def environments = new String[totalBundles]
def proxies = new Object[totalBundles][]
def appName = new String[totalBundles]
def appAttributeName = new String[totalBundles]
def appAttributeValue = new String[totalBundles]
def host = "example.com"
def USER = System.getenv('USER')
println "*** After Initialisation Read ***"
// Extract and Store Values
println "**** Read Variables ***"
for (int i = 0; i < totalBundles; i++) {
def bundle = configs.bundles[i]
// Products
productName[i] = bundle.product.name
approvalType[i] = "auto"
productAttributeName[i] = bundle.product.attributes[0].name
productAttributeValue[i] = bundle.product.attributes[0].value
displayName[i] = bundle.product.name
environments[i] = System.getenv('env') // Assuming 'env' is an environment variable
proxies[i] = bundle.product.proxies
// Developer
developer[i] = bundle.app.developer
firstName[i] = developer[i].takeWhile { it != '.' }
def start = developer[i].indexOf(".") + 1
def end = developer[i].indexOf("@")
lastName[i] = developer[i].substring(start, end).replaceAll(/[^a-zA-Z]/, "")
userName[i] = developer[i].takeWhile { it != '@' }
// Apps
appName[i] = bundle.app.name
appAttributeName[i] = bundle.app.attributes[0].name
appAttributeValue[i] = bundle.app.attributes[0].value
println "*** Print Apps & Products ***"
println "Product Name = $productName[i]"
println "App Name = $appName[i]"
println "Approval Type = $approvalType[i]"
println "Product Attributes Name = $productAttributeName[i]"
println "Product Attributes Value = $productAttributeValue[i]"
println "Display Name = $displayName[i]"
println "Environments = $environments[i]"
println "Proxies = ${proxies[i]}"
println "Developer = $developer[i]"
println "App Attributes Name = $appAttributeName[i]"
println "App Attributes Value = $appAttributeValue[i]"
}
for (int i = 0; i < totalBundles; i++) {
def productBody = """{
"approvalType": "${approvalType[i]}",
"attributes": [{"name": "${productAttributeName[i]}", "value": "${productAttributeValue[i]}"}],
"displayName": "${displayName[i]}",
"environments": ["${environments[i]}"],
"name": "${productName[i]}",
"proxies": ${proxies[i]}
}"""
println "Product Body = $productBody"
def developerBody = """{
"email": "${developer[i]}",
"firstName": "${firstName[i]}",
"lastName": "${lastName[i]}",
"userName": "${userName[i]}"
}"""
println "Developer Body = $developerBody"
def appBody = """{
"name": "${appName[i]}",
"apiProducts": ["${productName[i]}"],
"attributes": [{"name": "${appAttributeName[i]}", "value": "${appAttributeValue[i]}"}],
"keyExpiresIn": "31536000000"
}"""
println "App Body = $appBody"
// Products
def createProductResponse = sh(script: "curl -k -s -w '\\n%{response_code}' --header 'Authorization:Basic $USER' --header 'Content-Type: application/json' --data-binary '$productBody' --request POST https://${host}/apiproducts", returnStdout: true).trim()
println "$createProductResponse"
if (createProductResponse.contains('201')) {
println "*** Product ${productName[i]} created successfully ***"
} else if (createProductResponse.contains('409')) {
def updateProductResponse = sh(script: "curl -k -s -w '\\n%{response_code}' --header 'Authorization:Basic $USER' --header 'Content-Type: application/json' --data-binary '$productBody' --request PUT https://${host}/apiproducts/${productName[i]}", returnStdout: true).trim()
println "$updateProductResponse"
if (updateProductResponse.contains('200')) {
println "*** Product ${productName[i]} updated successfully ***"
} else {
error "Failed to update ${productName[i]} with $updateProductResponse"
}
} else {
error "Failed to create ${productName[i]} with $createProductResponse"
}
// Developers
def createDeveloperResponse = sh(script: "curl -k -s -w '\\n%{response_code}' --header 'Authorization:Basic $USER' --header 'Content-Type: application/json' --data-binary '$developerBody' --request POST https://${host}/developers", returnStdout: true).trim()
println "$createDeveloperResponse"
if (createDeveloperResponse.contains('201')) {
println "*** Developer ${developer[i]} created successfully ***"
} else if (createDeveloperResponse.contains('409')) {
println "*** Developer already exists: $createDeveloperResponse ***"
} else {
error "Failed to create ${developer[i]} with $createDeveloperResponse"
}
// Apps
def createAppResponse = sh(script: "curl -k -s -w '\\n%{response_code}' --header 'Authorization:Basic $USER' --header 'Content-Type: application/json' --data-binary '$appBody' --request POST https://${host}/developers/${developer[i]}/apps", returnStdout: true).trim()
println "$createAppResponse"
if (createAppResponse.contains('201')) {
println "*** App ${appName[i]} created successfully ***"
} else if (createAppResponse.contains('409')) {
def updateAppBody = """{
"attributes": [{"name": "${appAttributeName[i]}", "value": "${appAttributeValue[i]}"}]
}"""
println "Updated App Body = $updateAppBody"
def updateAppResponse = sh(script: "curl -k -s -w '\\n%{response_code}' --header 'Authorization:Basic $USER' --header 'Content-Type: application/json' --data-binary '$updateAppBody' --request PUT https://${host}/developers/${developer[i]}/apps/${appName[i]}", returnStdout: true).trim()
println "$updateAppResponse"
if (updateAppResponse.contains('200')) {
println "*** App ${appName[i]} updated successfully ***"
} else {
error "Failed to update ${appName[i]} with $updateAppResponse"
}
} else {
error "Failed to create ${appName[i]} with $createAppResponse"
}
}
Folder Structure:
I run into errors at most of the lines while running migrateToGitHubActions.yaml
Do GitHub Actions have fewer scripting capabilities than Jenkins? What kind of script is expected in Actions?
Error:
WARNING: An illegal reflective access operation has occurred WARNING: Illegal reflective access by org.codehaus.groovy.reflection.CachedClass (file:/usr/share/groovy/lib/groovy-2.4.17.jar) to method java.lang.Object.finalize() WARNING: Please consider reporting this to the maintainers of org.codehaus.groovy.reflection.CachedClass WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations WARNING: All illegal access operations will be denied in a future release Caught: groovy.lang.MissingPropertyException: No such property: json for class: java.io.File groovy.lang.MissingPropertyException: No such property: json for class: java.io.File at script.run(script.groovy:3) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) Error: Process completed with exit code 1.
I've tested your workflow configuration and the issue you are facing seems related to the groovy script.
After a few researches (and Chat GPT usage) I identified that some command lines you are using with Jenkins aren't available on Github Actions directly.
Example: the sh
commands is only available on Jenkins, you should replace this command line by execute
in your groovy script, this operation should then work when running the script in the workflow.
Moreover, I asked chat GPT to correct the first version of the groovy script you shared (I'm not familiar with groovy) and got the workflow to work here by using this workflow file - updating some actions versions - and this updated groovy script.
Note: If you face more issues with the groovy script, I suggest asking another question on StackOverflow with the groovy
tag, for the groovy community to give a more detailed answer.