Build Sports App using Gradle (OEDF) - KiltedKanuck/OpenEdgeOps GitHub Wiki

This section will describe how to compile ABL files, write ABLUnit tests, and package PAS for OpenEdge artifacts using Gradle and OpenEdge DevOps Framework (OEDF).

Tools & Technologies used

  1. OpenEdge (installed with Progress Dev AS for OE license)
  2. VSCode editor
  3. OpenEdge DevOps Framework (OEDF)
  4. Gradle
  5. GitHub

Login to the Windows VM

  1. Get the Windows VM details,
    • VM Hostname
    • Authentication password
  2. Use the Remote Desktop Connection app to log in to the above VM as Administrator user

Create your own GitHub project

  1. Open this GitHub repo in a browser and create a fork from it
    • For consistency use the default repo name
    • You can browse through the folders and files for a high-level understanding of the repo
  2. Now let's get those projects into your VM for development. In the Windows VM, create a folder named work at the C:\Users\Administrator location
  3. Open a Command Prompt terminal and navigate to the folder C:\Users\Administrator\work
  4. Clone GitHub repo
    git clone <https-clone-url-to-your-github-repo> 
    

Import Sports app in PDSOE

  1. Open a Progress Developer Studio for OpenEdge (PDSOE) workspace
  2. Import the project C:\Users\Administrator\work\pug2023OpenEdgeOps\Sports
    • Don't worry, if you see multiple compilation errors. The OpenEdge database connection is not configured with the project yet
  3. Let's create and start a Sports2020 database. Open proenv command line and type the below commands, [SKIP FOR THE WORKSHOP]
    mkdir db\sports
    cd db\sports
    prodb sports sports2020
    proserve sports -S 9876
    
  4. Come back to PDSOE, create a Database connection profile (Window -> Preferences -> Progress OpenEdge -> Database Connections), and point to the sports database created above
    • You can use the below values and leave the other fields empty
      Connection name: con_sports
      Physical name: C:\OpenEdge\WRK\db\sports\sports.db
      Service/port: 9876
      
    • Click Next until you see the Define Database Server Configuration page. Make sure to check both the Auto-start and Auto-shutdown database server options
    • Click Finish -> Apply
  5. Go to Project properties (Progress OpenEdge -> Database Connections) and attach the created Database connection to the project
  6. Restart OpenEdge AVM (<right-click-on-project> -> Progress OpenEdge -> Restart OpenEdge AVM)
  7. Clean and build the project (Project -> clean)
    • Check that the compilation errors will be fixed

Develop and make changes to the Sports app

  1. Open Customer.cls and navigate to the count method
  2. Check references (Find References) for the variable jsonParser and rename it to jParser at all the places inside the count method
  3. Run check syntax to confirm there are no compilation errors
  4. Open CustomerTest.cls and run the ABLUnit tests
  5. Check the export ABL Web Application

❓ What are the checks we perform for a change? Should you automate these steps? Why?

Automate the Compile, Test, and Package for OpenEdge projects

Enable Gradle for the Sports project

  1. Open VSCode and open the folder C:\Users\Administrator\work\pug2023OpenEdgeOps

  2. Open a Terminal in VSCode

    • Use a Command Prompt type of terminal
  3. Let's create a feature branch before we modify the project further,

    git checkout -b feature/enable-ci-cd
    

    â„šī¸ In general, the main branch is restricted from direct commits. You will be able to make changes locally but will not be able to push directly to the remote GitHub repo. Therefore, as a best practice, one should always work on a feature branch and merge it to the main repo using a Pull Request after reviews and tests are complete.

  4. Initialize a Gradle for the Sports project

    • Open proenv, navigate to the project root location and initialize Gradle
      cd C:\Users\Administrator\work\pug2023OpenEdgeOps\Sports
      progradle init
      
    • Press enter to keep the defaults for all of the options, except to ensure that the Select build script DSL is selected as Groovy.
    • Notice build.gradle file along with other Gradle files would have been generated. build.gradle file is the main build script where tasks are defined to do certain work such as compile, test, package, and so on.

Compile ABL files in the app

  1. Open build.gradle file in VSCode and add the below code to apply OEDF plugin,

    plugins { 
        id "progress.openedge.abl" version "2.2.1" 
    }
    

    â„šī¸ Since OEDF's latest version (2.2.1) doesn't support Gradle 8.x yet, update the Gradle version inside gradle\wrapper\gradle-wrapper.properties from 8.2.1 to 7.3.3. This will not be needed in future when you actually OE 12.8.

  2. Set DLC as environment variable - set DLC=C:/Apps/OE12.8LTS/DLC

  3. To see the list of default tasks present run the below command

    cd Sports
    gradlew tasks
    

    Notice tasks, especially under the sections ABL Compile tasks and ABL Database Connection tasks

  4. Configure the rcode output directory for the ABL Compile tasks

    tasks.named("compileAbl-root-AppServer"){
        rcodeDir = "${buildDir}/rcode/AppServer"
    }
    
    tasks.named("compileAbl-root-PASOEContent-WEB-INF-openedge"){
        rcodeDir = "${buildDir}/rcode/PASOEContent/WEB-INF/openedge"
    }
    
    tasks.named("compileAbl-root-tests-AppServer"){
        rcodeDir = "${buildDir}/rcode/tests/AppServer"
    }
    

    â„šī¸ There is an issue with OEDF's main ABL plugin where it is not honoring the output attribute of the PROPATH.

  5. Now, let's try to run the build task

    gradlew build
    

    There will be compilation errors due to Database connection details not being provided.

  6. Let's create a Sports 2020 database on the fly and configure it for the tasks. Copy the below code and paste it at the start of the build.gradle file just after the Plugins {} section

    // Gather required variables
    def stageEnv = System.getProperty("STAGE_ENVIRONMENT")
    stageEnv = stageEnv != null ? stageEnv : System.getenv("STAGE_ENVIRONMENT")
    def STAGE_ENVIRONMENT = stageEnv != null ? stageEnv : "dev"
    
    println "DLC: ${abl.dlcHome}"
    println "Stage Environment: ${STAGE_ENVIRONMENT}"
    
    group = 'com.progress.openedge'
    version = "1.0.0"
    description = 'Sports App'
    
    abl {
        if (STAGE_ENVIRONMENT == "dev") {
            dbConnection {
                dbName="${buildDir}/db/sports2020/sports"
                connectionParameters = "-1"
            }
        } else {
            dbConnection {
                parameterFile='conf/startup.pf'
            }
        }
    }
    
    // ABL App tasks
    task createSports2020(type: CreateDB){
        dbName = 'sports'
        sourceDb = "${dlcHome}/sports2020"
        outputDir = "${buildDir}/db/sports2020"
    }
    if (STAGE_ENVIRONMENT == "dev") {
        compileAbl.dependsOn "createSports2020"
    }
    
  7. Let's try to run the build task again

    ./gradlew build
    

    Notice, the compilation succeeded and rcode will be generated at the ${buildDir}/rcode location

Task for ABL Unit test

  1. Add the below code at the end of the build.gradle file,
    task testABLApp(type: ABLUnit){
        source("tests/AppServer")
        include("**/*Suite.cls")
        propath("tests/AppServer", "AppServer")
        outputDir = "${buildDir}/test-results/test"
        arguments = [haltOnFailure: "true"]
    }
    if (STAGE_ENVIRONMENT == "dev") {
        testABLApp.dependsOn "createSports2020"
    }
    check.dependsOn "testABLApp", "compileAbl"
    
  2. Run the build task again
    ./gradlew build
    
    Notice, that the ABLUnit tests ran and a summary will be printed in the terminal. You can also open the report file (Sports\build\test-results\test\results.xml) in a browser for a pretty view.

Task for packaging Web app

  1. Add the below code at the end of the build.gradle
    task packageWebApp(type: OEWar){
        webAppName = "Sports"
        archiveVersion = "" // to ignore version in the archive name, otherwise has to be handled during deployment
        verbose = true
        projectLocation = project.projectDir
        println "projectLocation: ${projectLocation.get()}"
        destinationDirectory = project.file "${project.distsDirectory.get()}/webapps"
    
        // exclude Sources from 'openedge' directory
        // (the ANT task used internally does it by default but added here anyway)
        exclude "PASOEContent/WEB-INF/openedge/*.(cls|p|i)"
    
        webInf {
            from("${buildDir}/rcode/PASOEContent/WEB-INF/openedge")
            into("openedge")
        }
    
        manifest {
            attributes "Implementation-Title": "My Sports ABL Web Application"
            attributes "Implementation-Version": "1.0.0"
            // from ("PASOEContent/META-INF/MANIFEST.MF")
        }
    }
    packageWebApp.dependsOn "compileAbl-root-PASOEContent-WEB-INF-openedge"
    assemble.dependsOn "packageWebApp"
    
  2. Run the build task again
    ./gradlew build
    
    Notice, that the WAR file is generated, build\distributions\webapps\Sports.war

Task for packaging ABL app

  1. Copy the below code at the end of the build.gradle file
    task packageABLApp(type: Oear) {
        ablAppName = "Sports"
        archiveVersion = ""
        destinationDirectory = project.file "${project.distsDirectory.get()}/ablapps"  //will create 'Sports.oear' file at this location
        tlr {
            from 'tlr'
            include '**/*.properties'
            include '**/*.xml'
        }
        webapps {
            from "${project.distsDirectory.get()}/webapps"
            include '**/*.war'
            include '**/*.zip'
        }
        openedge {
            from "${buildDir}/rcode/AppServer"
            include '**/*.r'
        }
        conf {
            from 'conf'
            exclude '**/*.MF'   //exclude direct copy of manifest file and append using manifest section
        }
        manifest {
            attributes "Implementation-Title": "My Sports ABL Application"
            attributes "Implementation-Version": "1.0.0"
            // from ("conf/MANIFEST.MF")
        }
    }
    packageABLApp.dependsOn "compileAbl-root-AppServer"
    packageABLApp.dependsOn "packageWebApp"
    assemble.dependsOn "packageABLApp"
    
  2. Run the build task again
    ./gradlew build
    
    Notice, that the OEAR file is generated, build\distributions\ablapps\Sports.oear

This completes the build steps in the local VM setup. After the local changes, we tested compile, unit test, and package locally. Now let's push the changes to remote GitHub repo and work on creating a CI pipeline.

git add <files-added>
git commit -m "OEDF scripts for building Sports app"
git push origin feature/enable-ci-cd

If you don't have Git client configured, you need to do that. - Add the user git config --global user.email "<email-id>" - Sign in while pushing to remote rep


Go to the Setup CI Pipeline Activity

âš ī¸ **GitHub.com Fallback** âš ī¸