Forum OpenACS Development: Re: Run APM Upgrades automatically

Collapse
Posted by Gustaf Neumann on
The changes in the OpenACS CVS repository happin in two phases, (a) commits, and (b) tagging. In theory, all committed changes should be tested locally, and when the packages are passing the end-user tests, these are (CVS-) tagged for release. Only tagged changes are picked up over the release branches via APM (one can pick up all versions form the HEAD branch).

We have spent during the last year much effort to improve the regression tests, but it is still a long way to go to fully rely on it. The testing coverage is still not suficient on it in the sense of continues integration/deployment (CI/CD). It would be certainly cool to change from the manual tagging to an automated APM releasing based on the tests, but for now we concentrate on the release of OpenACS 5.10.

Historically, OpenACS core releases were releases, when these pass the regression tests in a acs-core only installation. The installation of further packages (forums, news, file-storage) already lead to several failures due to simple things like naming constraints and the like. One goal of the OpenACS 5.10 release would be to run the regression test cleanly with the major packages installed).

Collapse
Posted by Malte Sussdorff on
Okay. I understood the part about the regression tests and not fit for CI/CD yet.

I honestly was more looking into the problem I have with the workflow as follows:

- After (extensive) manual testing, I deem custom packages ready to work.
- I build a new container with the release code.

What I would love to do now:
- Fire up the container with a pg_dump from each customer
- Test if the upgrade scripts work (so all the package-install scripts)
- Run any regression tests we have
- Run Sencha Tests for the sencha apps which connect to the OpenACS / ]project-open[ backend (so I can eventually lessen the extensive manual testing)

In Theory I could structure my first "test" to simulate EndUser behaviour to run through the website (like Selenium tests) and see if we pick up any errors on the way. Or write an "apm_upgrade_package" function, which combines the result of package-install-1-4 in one script.

So as you can see, I am stuck miles behind your thinking (with automated installs from the APM repository) and still hung up on getting upgrades working in an automated fashion so I can test that these don't throw errors (depending on environment). But that seems a prerequisite to actually testing the code afterwards.

Collapse
Posted by Héctor Romojaro on
Hi Malte,

i have been also dealing with some CI/CD as well, including automated packages upgrade, automated testing, and so on...

I wrote the following code, which is called from a pipeline job on our CI tool, via curl, in order to automatically upgrade all possible packages, or a single package + its dependencies, if package_key is passed.

In our setup, this is run in a brand new instance inside a docker container, and the error.log is parsed by our CI tool, grepping for certain strings to determine the result of the job, if upgrades were successful or not. The error.log is then made available as a job artifact, in case it needs to be inspected to check if something went wrong.

Hope it helps, i have simplified it a bit removing certain particularities of our own setup, so test it at your own risk :)

ad_page_contract {
    Upgrade required packages
} {
    {package_key:token ""}
}

# Headers
ns_headers 200 text/plain

#
# Vars
#
set pad 80
set all_fine true
#
# Print header
#
ns_write "* OpenACS package upgrade\n"
ns_write "=========================\n"
#
# Retrieve all spec files
#
set packages_spec_files     [apm_scan_packages "$::acs::rootdir/packages"]
set workspace_spec_files    [apm_scan_packages [apm_workspace_install_dir]]
set workspace_filenames     [list]
foreach spec_path $workspace_spec_files {
    lappend workspace_filenames [file tail $spec_path]
}
set all_spec_files $workspace_spec_files
foreach spec_path $packages_spec_files {
    set spec_filename [file tail $spec_path]
    if {$spec_filename ni $workspace_filenames} {
        lappend all_spec_files $spec_path
    }
}
#
# Parse the files and make a list of available packages to upgrade
#
set packages_to_upgrade [list]
foreach spec_file $all_spec_files {
    array set version    [apm_read_package_info_file $spec_file]
    set this_version     $version(name)
    set this_package_key $version(package.key)
    #
    # Filter by package_key, if passed as an argument, and check for upgrades
    #
    if {($package_key eq "" || $package_key eq $this_package_key) &&
        [apm_package_supports_rdbms_p -package_key $this_package_key] &&
        [apm_package_registered_p $this_package_key] &&
        [apm_package_installed_p $this_package_key] &&
        [apm_higher_version_installed_p $this_package_key $this_version] eq 1
    } {
        #
        # Add the package to the list
        #
        lappend packages_to_upgrade $this_package_key
    }
}
#
# Are there packages to upgrade?
#
if {$packages_to_upgrade ne ""} {
    #
    # Dependency check
    #
    apm_get_package_repository -array repository
    apm_get_installed_versions -array installed
    ns_log notice "ci-packages-upgrade: run apm_dependency_check_new with <$packages_to_upgrade>"
    array set result [apm_dependency_check_new \
                          -repository_array repository \
                          -package_keys $packages_to_upgrade]
    ns_log notice "ci-packages-upgrade: apm_dependency_check_new with <$packages_to_upgrade>: [array get result]"
    if {$result(status) eq "ok"} {
        #
        # Do the upgrade
        #
        foreach package_key $result(install) {
            #
            # As we may have new packages included by the dependency check,
            # determine if we are upgrading or installing.
            #
            set spec_file       [apm_package_info_file_path $package_key]
            array set version   [apm_read_package_info_file $spec_file]
            set new_version     $version(name)
            if { [apm_package_upgrade_p $package_key $new_version] == 1} {
                set installed_version [apm_highest_version_name $package_key]
                ns_write "[ad_pad -right "* Upgrade $package_key ($installed_version -> $new_version) ..." $pad " "]"
                ns_log Warning "ci-packages-upgrade: $package_key ($installed_version -> $new_version)"
            } else {
                set installed_version ""
                ns_write "[ad_pad -right "* Install $package_key ($new_version) ..." $pad " "]"
                ns_log Warning "ci-packages-upgrade: $package_key (fresh install $new_version)"
            }
            #
            # Select SQL scripts
            #
            set data_model_files [apm_data_model_scripts_find \
                                      -upgrade_from_version_name $installed_version \
                                      -upgrade_to_version_name $new_version \
                                      $package_key]
            ns_log Warning "ci-packages-upgrade: $package_key datamodel files: $data_model_files"
            #
            # Upgrade the package
            #
            if {[catch {
                ns_log notice "===== INSTALL $package_key"
                set version_id [apm_package_install \
                        -enable=1 \
                        -load_data_model \
                        -data_model_files $data_model_files \
                        $spec_file]
                #
                # Upgrade successful
                #
                ns_log notice "===== INSTALL $package_key DONE"
                ns_write "Ok\n"
            } errorMsg]} {
                #
                # Upgrade failed
                #
                ns_write "Error\n"
                set all_fine false
                ns_log Error "ci-packages-upgrade: $package_key $errorMsg\n [ns_quotehtml $::errorInfo]"
            }
        }
    } else {
        #
        # Dependency check error
        #
        ns_write "* Dependency check failed\n"
        set all_fine false
    }
} else {
    #
    # Nothing to do
    #
    ns_write "* No upgrades required\n"
}
#
# All fine?
#
ns_write "* Done!\n"
if {$all_fine} {
    #
    # Grepped by CI pipeline to check if all upgrades were successful.
    #
    ns_log Warning "ci-packages-upgrade: all packages up-to-date."
} else {
    ns_log Warning "ci-packages-upgrade: upgrade failed."
    ns_write "=========================\n"
    ns_write "* Errors where found during package upgrade. Please check the error.log for details.\n"
}