はじめに
ヘルスケアの相互運用環境では、InterSystems Health Connectは、プロダクション、ビジネスプロセス、オペレーション、サービス、ユーティリティクラス、ルーチン、その他のObjectScriptのアーティファクトなどの重要なコンポーネントを通常含んでいます。伝統的に、これらのコンポーネントの多くのデプロイは、クラスをコピーすること、XMLをインポートすること、または管理ポータルからの管理ツールを使用することによって手動で行われてきました。
このアプローチは初期段階では機能するかもしれないが、プロジェクトが成長し、複数の開発者が並行して作業している場合、または開発、統合、ステージング、本番といった環境間で繰り返しデプロイが必要な場合、維持することが難しくなる。
より堅牢な代替案は、継続的インテグレーション内でHealth Connectを統合することである。 フローを、Git をソースコードリポジトリとして、Jenkins をデプロイメントオーケストレーターとして使用します。
本稿の目的は、以下の実践的なアプローチを示すことです:
- GitHub で Health Connect コードのバージョニング。
- 最後のデプロイ以降に変更されたファイルのみを検出。
- それらのファイルをステージングフォルダにコピー。
- 変更を Health Connect ネームスペースにロードおよびコンパイル。
- Jenkinsを通じてSSHを使用して完全なプロセスをリモートで実行します.
アーキテクチャ.
例として、以下の要素を設定しました.
ヘルスインスタンス用のIRIS.
私はInterSystems IRIS for HealthをAWSのRHEL10マシンにデプロイし、独自のApacheサーバーを設定し、HTTPおよびSSH経由の接続を有効にしました.
開発のために、私はVisual Studio CodeをローカルのIRISインスタンスで動作させるように設定しました。そこでコードの変更を行い、その後GitHubにアップロードします。
GitHubリポジトリ
私たちはバージョン管理システムとしてGitHubを選びました。Visual Studio Codeで利用可能な拡張機能を活用することで、必要に応じてブランチで作業することができます。
この要素はCI/CDプロセスにとって重要で、最新のデプロイ用に開発されたコードを入手できる場所だからです。
Jenkins
Jenkinsを知らない方々のために、これはオープンソースの自動化サーバーで、継続的統合プロセスに広く使用されており、多くのプラグインがあるため、作業を簡単にすることができます。
JenkinsにはGroovyスクリプトツールがあり、私たちが統合プロセスの必要なステップを実装できるようにします。この例では、あまり複雑になりません。
統合手順
この例では、AWSサーバー上でデプロイされたDEVELOPMENTインスタンス(開発のための相互運用性プロジェクト)で作業していると仮定します。ここでは、開発者がローカルインスタンスで行った変更をテストのために対応するGitHubリポジトリのブランチにデプロイしたいと考えています。手順は概ね以下のようになります:
- 開発者はローカルインスタンスに機能を実装します。
- 開発者は変更を対応するGitHubリポジトリのブランチにアップロードします。
- デプロイ責任者はJenkinsにアクセスしパイプラインを起動します.
- JenkinsはSSH経由でDEVELOPMENTサーバーに接続します.
- サーバー上でLinuxスクリプトが実行されています.
- スクリプトはリポジトリから最新の変更をgit pullを使用してダウンロードします.
- このスクリプトはサーバーディレクトリにコピーされる新規または変更されたファイルを特定します.
- ファイルが特定されると、スクリプトはObjectScript内の2番目のスクリプトを呼び出します。
- 2番目のスクリプトはファイルをIRIS for Healthインスタンスにロードしてコンパイルします。
- アップロードが成功した場合、スクリプトは生産を再起動します。
ご覧の通り、私たちは非常に基本的な操作を選択しましたが、それでもかなり役立つものです。
Jenkinsを使用してDEVELOPMENTサーバーで実行するスクリプトを見てみましょう:
#!/usr/bin/env bash
set -euo pipefail
=========================
Configuration
=========================
REPO_URL="https://github.com/intersystems-ib/workshop-cicd-demo"
BRANCH="main"
Local clone used to compare commits
CACHE_REPO="/opt/git-cache/project_repo"
Folder to copy the files to be uploaded into Health Connect
EXPORT_DIR="/projectGit"
File with the latest processed commit
STATE_FILE="${CACHE_REPO}/.last_sync_commit"
CLean up EXPORT_DIR before to copy the new updates
CLEAN_EXPORT_DIR="true"
=========================
Validations
=========================
if ! command -v git >/dev/null 2>&1; then
echo "Error: git is not installed."
exit 1
fi
mkdir -p "${EXPORT_DIR}"
mkdir -p "$(dirname "${CACHE_REPO}")"
=========================
Clone or update cache folder
=========================
if [ ! -d "${CACHE_REPO}/.git" ]; then
echo "Cloning repository into cache..."
git clone --branch "${BRANCH}" "${REPO_URL}" "${CACHE_REPO}"
else
echo "Updating local cache..."
git -C "${CACHE_REPO}" fetch origin
git -C "${CACHE_REPO}" checkout "${BRANCH}"
git -C "${CACHE_REPO}" reset --hard "origin/${BRANCH}"
fi
REMOTE_COMMIT="$(git -C "${CACHE_REPO}" rev-parse HEAD)"
=========================
First execution
=========================
if [ ! -f "${STATE_FILE}" ]; then
echo "First execution."
echo "Copying all the contains from branch into ${EXPORT_DIR}..."
if [ "${CLEAN_EXPORT_DIR}" = "true" ]; then
find "${EXPORT_DIR}" -mindepth 1 -maxdepth 1 -exec rm -rf {} +
fi
rsync -av --delete --exclude ".git" "${CACHE_REPO}/" "${EXPORT_DIR}/"
echo "${REMOTE_COMMIT}" > "${STATE_FILE}"
echo "First export finished."
exit 0
fi
LAST_COMMIT="$(cat "${STATE_FILE}")"
if [ "${LAST_COMMIT}" = "${REMOTE_COMMIT}" ]; then
echo "No updates."
exit 0
fi
echo "Comparing commits:"
echo " anterior: ${LAST_COMMIT}"
echo " actual: ${REMOTE_COMMIT}"
if [ "${CLEAN_EXPORT_DIR}" = "true" ]; then
echo "Cleaning up export folder..."
find "${EXPORT_DIR}" -mindepth 1 -maxdepth 1 -exec rm -rf {} +
fi
=========================
Export just added or modified files
=========================
while IFS= read -r -d '' status && IFS= read -r -d '' path1; do
case "${status}" in
M|A)
echo "Exporting ${status}: ${path1}"
mkdir -p "${EXPORT_DIR}/$(dirname "${path1}")"
cp -f "${CACHE_REPO}/${path1}" "${EXPORT_DIR}/${path1}"
;;
D)
# Ignoring deletes
echo "Ignoring deleted: ${path1}"
;;
R*)
IFS= read -r -d '' path2
echo "Exporting renamed: ${path1} -> ${path2}"
mkdir -p "${EXPORT_DIR}/$(dirname "${path2}")"
cp -f "${CACHE_REPO}/${path2}" "${EXPORT_DIR}/${path2}"
;;
*)
echo "Change not automatically managed: ${status} ${path1}"
;;
esac
done < <(git -C "${CACHE_REPO}" diff --name-status -z "${LAST_COMMIT}" "${REMOTE_COMMIT}")
echo "${REMOTE_COMMIT}" > "${STATE_FILE}"
echo "Incremental export concluded in ${EXPORT_DIR}"
echo "Starting file upload and compile in Health Connect"
(echo '_system'; echo 'SYS'; cat iris.script) | iris session IRISHEALTH
echo "Compilation successfully finished"
ご覧の通り、このスクリプトは私たちのGitHubリポジトリ上でgit pullを実行し、DEVELOPMENTサーバーのディレクトリ内のソースコードを更新し、最後にダウンロードしたバージョンと比較して変更を検出し、それらを2番目のディレクトリ(/projectGit)に抽出し、最後にIRISスクリプトを呼び出します。
(echo '_system'; echo 'SYS'; cat iris.script) | iris session IRISHEALTH
最初の2つのエココマンドは、私たちが実行するObjectScriptスクリプトに必要なターミナルセッションにユーザー名とパスワードを渡すために使います
zn "DEMO"
set sc = $SYSTEM.OBJ.LoadDir("/projectGit/src/Demo", "ck", , 1)
if '$SYSTEM.Status.IsOK(sc) do $SYSTEM.Status.DisplayError(sc) quit
set production = "Demo.Order.Production"
set ^Ens.Configuration("csp","LastProduction") = production
do ##class(Ens.Director).SetAutoStart(production)
do ##class(Ens.Director).StartProduction(production)
write !,"Produccion iniciada correctamente: ",production,!
このスクリプトは、私たちが修正または作成したクラスをインポートし、コンパイルする場所です。コンパイルが成功した場合、私たちのDEMO名前空間の対応する生産環境を再起動して、変更が実装されます。
完璧です。私たちはスクリプト、DEVELOPMENTサーバー、そしてGitHubを持っています。Jenkinsを設定しましょう.
Jenkinsの設定
パイプラインを作成する前に、私たちは主要なユーザー名とパスワードを使ってDEVELOPMENTサーバーにSSHで接続できるようにするプラグインをインストールする必要があります.
Jenkinsの設定から、私たちはDEVELOPMENTサーバーへのアクセス資格情報を作成しました:
最後にパイプラインを作成します。
パイプラインの設定内で、以下のスクリプトを定義します。これによりデプロイが可能になります。
pipeline {
agent any
parameters {
string(name: 'GIT_BRANCH', defaultValue: 'main', description: 'Repository branch')
string(name: 'REMOTE_HOST', defaultValue: 'ec2-**-**-***-**.**-*****.compute.amazonaws.com', description: 'Remote Host')
string(name: 'REMOTE_USER', defaultValue: 'ec2-user', description: 'Remote SSH user')
string(name: 'REMOTE_SCRIPT_NAME', defaultValue: 'shell_script.sh', description: 'Remote script name')
}
environment {
REPO_URL = 'https://github.com/intersystems-ib/workshop-cicd-demo'
SSH_CREDENTIALS_ID = 'ssh-healthconnect-remote'
}
stages {
stage('Checkout') {
steps {
git branch: "${params.GIT_BRANCH}", url: "${env.REPO_URL}"
}
}
stage('Validate script') {
steps {
sh '''
set -eu
test -f shell_script.sh
chmod +x shell_script.sh
'''
}
}
stage('Launch remote script') {
steps {
sshagent(credentials: ["${env.SSH_CREDENTIALS_ID}"]) {
sh '''
set -eu
ssh -o StrictHostKeyChecking=no "${REMOTE_USER}@${REMOTE_HOST}" \
"sudo sh '/${REMOTE_SCRIPT_NAME}'" | tee remote_execution.log
'''
}
}
}
}
post {
always {
archiveArtifacts artifacts: 'remote_execution.log', allowEmptyArchive: true
}
success {
echo 'Remote deployment successfully finished.'
}
failure {
echo 'Remote deployment failed. Check remote_execution.log.'
}
}
}
私たちのスクリプトは何をしますか?非常に簡単で、GitHubリポジトリが存在し、関連するブランチがあるかを確認し、その後SSH経由でLinuxスクリプトを実行する指示を送ります。そのLinuxスクリプトは、インスタンスをダウンロードおよび更新する責任を持ちます。
小さな例で実際の動作を見てみましょう.
プロセスを実行しています
私たちの生産は正常に運行しており、コンポーネントの1つを変更して、パラメータの1つで表示されるデフォルト値が異なるようにしたいです.

今、私たちはTenantId パラメータに値 ZZZ-999 を設定する、素晴らしい、私たちのローカルインスタンスの Visual Studio Code にあるコードを修正し、変更を GitHub にアップロードしよう.
変更がリポジトリにプッシュされたので、私たちの Jenkins インスタンスからパイプラインを実行できる。パイプラインの出力を見てみよう.
全てが正しい;変更を検知し、スクリプトを正常に実行した。
パラメータが変更されたかどうかを確認し、本番環境が正常に再起動したかどうかを確認しましょう.
これで新しいTenantIdが手に入りました!完全に、打って変わっての成功です!
結論と次のステップ.
お気づきかもしれませんが、IRISには継続的インテグレーションプロセスに参加するための技術的な制限はありません。あなたの日常的な運用に最適な適切なスクリプトが必要なだけです。
本記事では、ヘルスのためのIRISとの連続統合の小さな例を見ましたが、これはConfiguration Mergeなどの機能を使用してデプロイできる特定の設定に拡張できます.
試してみてください!























