Skip to content

Commit

Permalink
Merge branch 'develop' into bugfix/jjob_prepoceanobs
Browse files Browse the repository at this point in the history
  • Loading branch information
AndrewEichmann-NOAA authored Apr 4, 2024
2 parents e43ce9a + 108ce2a commit be2ac41
Show file tree
Hide file tree
Showing 195 changed files with 6,462 additions and 6,899 deletions.
16 changes: 0 additions & 16 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -156,20 +156,8 @@ sorc/ocnicepost.fd
# Ignore scripts from externals
#------------------------------
# jobs symlinks
jobs/JGFS_ATMOS_WAFS
jobs/JGFS_ATMOS_WAFS_BLENDING
jobs/JGFS_ATMOS_WAFS_BLENDING_0P25
jobs/JGFS_ATMOS_WAFS_GCIP
jobs/JGFS_ATMOS_WAFS_GRIB2
jobs/JGFS_ATMOS_WAFS_GRIB2_0P25
# scripts symlinks
scripts/exemcsfc_global_sfc_prep.sh
scripts/exgfs_atmos_wafs_blending.sh
scripts/exgfs_atmos_wafs_blending_0p25.sh
scripts/exgfs_atmos_wafs_gcip.sh
scripts/exgfs_atmos_wafs_grib.sh
scripts/exgfs_atmos_wafs_grib2.sh
scripts/exgfs_atmos_wafs_grib2_0p25.sh
# ush symlinks
ush/chgres_cube.sh
ush/emcsfc_ice_blend.sh
Expand All @@ -185,11 +173,7 @@ ush/global_chgres_driver.sh
ush/global_cycle.sh
ush/global_cycle_driver.sh
ush/jediinc2fv3.py
ush/mkwfsgbl.sh
ush/ufsda
ush/wafs_blending.sh
ush/wafs_grib2.regrid.sh
ush/wafs_intdsk.sh
ush/finddate.sh
ush/make_NTC_file.pl
ush/make_ntc_bull.pl
Expand Down
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,7 @@
[submodule "sorc/gsi_monitor.fd"]
path = sorc/gsi_monitor.fd
url = https://github.com/NOAA-EMC/GSI-Monitor.git
[submodule "sorc/upp.fd"]
path = sorc/upp.fd
url = https://github.com/NOAA-EMC/UPP.git
ignore = dirty
3 changes: 3 additions & 0 deletions .shellcheckrc
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@ disable=SC1091

# Disable -p -m only applies to deepest directory
disable=SC2174

# Disable warning of functions in test statements
disable=SC2310
87 changes: 64 additions & 23 deletions ci/Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ def Machine = 'none'
def machine = 'none'
def HOME = 'none'
def caseList = ''
// Location of the custom workspaces for each machine in the CI system. They are persitent for each iteration of the PR.
def custom_workspace = [hera: '/scratch1/NCEPDEV/global/CI', orion: '/work2/noaa/stmp/CI/ORION', hercules: '/work2/noaa/stmp/CI/HERCULES']

pipeline {
Expand Down Expand Up @@ -82,13 +83,43 @@ pipeline {
}
} else {
checkout scm
def gist_url = ""
def error_logs = ""
def error_logs_message = ""
def builds_file = readYaml file: 'ci/cases/yamls/build.yaml'
def build_args_list = builds_file['builds']
def build_args = build_args_list[system].join(' ').trim().replaceAll('null', '')
dir("${HOMEgfs}/sorc") {
sh(script: "${build_args}")
try {
sh(script: "${build_args}")
} catch (Exception error_build) {
echo "Failed to build system: ${error_build.getMessage()}"
if ( fileExists("logs/error.logs") ) {
def fileContent = readFile 'logs/error.logs'
def lines = fileContent.readLines()
for (line in lines) {
echo "archiving: ${line}"
if (fileExists("${line}") && readFile("${line}").length() > 0 ){
try {
archiveArtifacts artifacts: "${line}", fingerprint: true
error_logs = error_logs + "${HOMEgfs}/sorc/${line} "
error_logs_message = error_logs_message + "${HOMEgfs}/sorc/${line}\n"
}
catch (Exception error_arch) { echo "Failed to archive error log ${line}: ${error_arch.getMessage()}" }
}
}
repo_url=sh(script: "${HOMEgfs}/ci/scripts/utils/publish_logs.py --file ${error_logs} --repo PR_BUILD_${env.CHANGE_ID}", returnStdout: true).trim()
gist_url=sh(script: "${HOMEgfs}/ci/scripts/utils/publish_logs.py --file ${error_logs} --gist PR_BUILD_${env.CHANGE_ID}", returnStdout: true).trim()
try {
pullRequest.comment("Build failed on **${Machine}** with error logs:${error_logs_message}\n\nFollow link here to view the contents of the above file(s): [(link)](${gist_url})")
} catch (Exception error_comment) {
echo "Failed to comment on PR: ${error_comment.getMessage()}"
}
error("Failed to build system on ${Machine}")
}
}
sh(script: './link_workflow.sh')
sh(script: "echo ${HOMEgfs} > BUILT_semaphor")
// sh(script: "echo ${HOMEgfs} > BUILT_semaphor")
}
}
if (env.CHANGE_ID && system == 'gfs') {
Expand Down Expand Up @@ -147,40 +178,50 @@ pipeline {
steps {
script {
HOMEgfs = "${HOME}/gfs" // common HOMEgfs is used to launch the scripts that run the experiments
ws(HOMEgfs) {
pslot = sh(script: "${HOMEgfs}/ci/scripts/utils/ci_utils_wrapper.sh get_pslot ${HOME}/RUNTESTS ${Case}", returnStdout: true).trim()
try {
sh(script: "${HOMEgfs}/ci/scripts/run-check_ci.sh ${HOME} ${pslot}")
} catch (Exception e) {
sh(script: "${HOMEgfs}/ci/scripts/utils/ci_utils_wrapper.sh cancel_all_batch_jobs ${HOME}/RUNTESTS")
ws(HOME) {
if (fileExists('RUNTESTS/error.logs')) {
def error_logs = sh(script: "cat RUNTESTS/error.logs", returnStdout: true).trim()
try {
pullRequest.comment("Experiment ${Case} failed on ${Machine}\n\nError logs:\n\n${error_logs}")
} catch (Exception error) {
echo "Failed to comment on PR: ${error.getMessage()}"
}
def fileContent = readFile 'RUNTESTS/error.logs'
def lines = fileContent.readLines()
for (line in lines) {
echo "archiving: ${line}"
archiveArtifacts artifacts: "${line}", fingerprint: true
pslot = sh(script: "${HOMEgfs}/ci/scripts/utils/ci_utils_wrapper.sh get_pslot ${HOME}/RUNTESTS ${Case}", returnStdout: true).trim()
try {
sh(script: "${HOMEgfs}/ci/scripts/run-check_ci.sh ${HOME} ${pslot}")
} catch (Exception error_experment) {
sh(script: "${HOMEgfs}/ci/scripts/utils/ci_utils_wrapper.sh cancel_all_batch_jobs ${HOME}/RUNTESTS")
ws(HOME) {
def error_logs = ""
def error_logs_message = ""
if (fileExists("RUNTESTS/error.logs")) {
def fileContent = readFile 'RUNTESTS/error.logs'
def lines = fileContent.readLines()
for (line in lines) {
echo "archiving: ${line}"
if (fileExists("${HOME}/${line}") && readFile("${HOME}/${line}").length() > 0) {
try {
archiveArtifacts artifacts: "${line}", fingerprint: true
error_logs = error_logs + "${HOME}/${line} "
error_logs_message = error_logs_message + "${HOME}/${line}\n"
} catch (Exception error_arch) {
echo "Failed to archive error log ${line}: ${error_arch.getMessage()}"
}
}
}
repo_url = sh(script: "${HOMEgfs}/ci/scripts/utils/publish_logs.py --file ${error_logs} --repo PR_${env.CHANGE_ID}", returnStdout: true).trim()
gist_url = sh(script: "${HOMEgfs}/ci/scripts/utils/publish_logs.py --file ${error_logs} --gist PR_${env.CHANGE_ID}", returnStdout: true).trim()
try {
pullRequest.comment("Experiment ${Case} failed on ${Machine} with error logs: ${error_logs_message}\n\nFollow link here to view the contents of the above file(s): [(link)](${gist_url})")
} catch (Exception error_comment) {
echo "Failed to comment on PR: ${error_comment.getMessage()}"
}
} else {
echo "No error logs found for failed cases in $HOME/RUNTESTS/error.logs"
}
error("Failed to run experiments ${Case} on ${Machine}")
}
}
}
}
}

}
}
}
}

post {
always {
script {
Expand Down
1 change: 1 addition & 0 deletions ci/cases/pr/C48_S2SWA_gefs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ arguments:
idate: 2021032312
edate: 2021032312
yaml: {{ HOMEgfs }}/ci/cases/yamls/gefs_ci_defaults.yaml

1 change: 1 addition & 0 deletions ci/cases/pr/C48mx500_3DVarAOWCDA.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ arguments:

skip_ci_on_hosts:
- orion
- hera
- hercules
4 changes: 2 additions & 2 deletions ci/cases/yamls/build.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
builds:
- gefs: './build_all.sh'
- gfs: './build_all.sh -wgu'
- gefs: './build_all.sh -k'
- gfs: './build_all.sh -kwgu'
124 changes: 124 additions & 0 deletions ci/scripts/utils/githubpr.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#!/usr/bin/env python3

import os
import re

from github import Github, GithubException, InputFileContent, UnknownObjectException
from wxflow import which


class GitHubDBError(Exception):
"""
Base class for GitHubDB exceptions.
"""
UnknownObjectException = UnknownObjectException
GithubException = GithubException


class GitHubPR(Github):
"""
GitHubPR is an inherited class from GitHub in pyGitHub for interacting with GitHub pull requests.
Attributes
----------
repo : github.Repository.Repository
The GitHub repository to interact with.
pulls : github.PaginatedList.PaginatedList of github.PullRequest.PullRequest
The list of open pull requests in the repository, sorted by last updated.
user : github.AuthenticatedUser.AuthenticatedUser
The authenticated user.
InputFileContent : github.InputFileContent.InputFileContent
The class used to create file content for gists.
Methods
-------
__init__(self, repo_url=None, TOKEN=None)
Initialize a new GitHubPR instance.
get_repo_url(self, repo_url=None)
Set the repository for the GitHubPR instance
using an URL directly or from 'REPO_URL' environment variable.
get_pr_list(self)
Get the numerical list of all pull requests.
get_ci_pr_list(self, state='Ready', host=None)
Get the numerical list of all pull requests with a specific state from labels.
for example if a PR has a label 'CI-Ready-Hera' of the form CI-[state]-[host]
its corresponding PR number will be included in the list.
"""

def __init__(self, repo_url=None, TOKEN=None):
"""
__init__ Initialize a new GitHubPR instance.
This method authenticates with the GitHub API using the 'gh' CLI tool
when the TOKEN is not provided. The repository comes from from the 'REPO_URL'
environment variable when repo_url is not provided.
"""
if TOKEN is None:
gh_cli = which('gh')
gh_cli.add_default_arg(['auth', 'status', '--show-token'])
TOKEN = gh_cli(output=str, error=str).split('\n')[3].split(': ')[1]
super().__init__(TOKEN)

self.repo = self.get_repo_url(repo_url)
self.pulls = self.repo.get_pulls(state='open', sort='updated', direction='desc')
self.user = self.get_user()

self.InputFileContent = InputFileContent

def get_repo_url(self, repo_url=None):
"""
set_repo Set the repository for the GitHubPR instance.
Parameters
----------
repo_url : Repository URL
The GitHub repository.
"""
if repo_url is None:
repo_url = os.environ.get("REPO_URL")
match = re.search(r"github\.com/(.+)", repo_url)
repo_identifier = match.group(1)[:-4]
return self.get_repo(repo_identifier)

def get_pr_list(self):
"""
get_pr_list Get the numerical list of all pull requests.
Returns
-------
list
A list of all pull request numbers.
"""
return [pull.number for pull in self.pulls]

def get_ci_pr_list(self, state='Ready', host=None):
"""
get_ci_pr_list Get a list of pull requests that match a specified state and host.
Parameters
----------
state : str, optional
The state of the pull requests to get (default is 'Ready').
host : str, optional
The host of the pull requests to get. If None, all hosts are included (default is None).
Returns
-------
list
A list of pull request numbers that match the specified state and host.
"""
pr_list = []
for pull in self.pulls:
labels = pull.get_labels()
ci_labels = [s for s in labels if 'CI' in s.name]
for label in ci_labels:
if state in label.name:
if host is not None:
if host.lower() in label.name.lower():
pr_list.append(pull.number)
break
else:
pr_list.append(pull.number)
break

return pr_list
Loading

0 comments on commit be2ac41

Please sign in to comment.