This guide provides detailed instructions for deploying the latest development code to QA1 and QA2 environments.
The HMIS project uses GitHub Actions for automated CI/CD deployment to QA environments. Deployments are triggered by pushing code to specific branch names that correspond to each environment.
IMPORTANT: Before any QA deployment, verify that src/main/resources/META-INF/persistence.xml is properly configured:
Run these commands before deploying:
# 1. Check JNDI datasources use environment variables
grep '<jta-data-source>' src/main/resources/META-INF/persistence.xml
# 2. Check for hardcoded DDL generation paths
grep -i "eclipselink.application-location" src/main/resources/META-INF/persistence.xmlJNDI Datasources:
<jta-data-source>${JDBC_DATASOURCE}</jta-data-source>
<jta-data-source>${JDBC_AUDIT_DATASOURCE}</jta-data-source>DDL Generation: Should NOT contain hardcoded paths
<!-- These lines should NOT exist in deployment persistence.xml -->
<!-- <property name="eclipselink.application-location" value="c:/tmp/"/> -->Hardcoded JNDI:
<jta-data-source>jdbc/coop</jta-data-source>
<jta-data-source>jdbc/ruhunuAudit</jta-data-source>Hardcoded DDL paths:
<property name="eclipselink.application-location" value="c:/tmp/"/>
<property name="eclipselink.ddl-generation" value="create-or-extend-tables"/>The GitHub Actions workflow automatically replaces environment variables with environment-specific values during build.
| Environment | Branch Name | Application URL | JDBC DataSource |
|---|---|---|---|
| QA1 | hims-qa1 |
https://qa.carecode.org/qa1 | jdbc/qa, jdbc/qaAudit |
| QA2 | hims-qa2 |
https://qa.carecode.org/qa2 | jdbc/coop, jdbc/coopAudit |
| QA3 | hims-qa3 |
https://qa.carecode.org/qa3 | jdbc/qa3, jdbc/qa3audit |
IMPORTANT: Complete ALL prerequisites before proceeding
-
Install and authenticate GitHub CLI:
# Check if gh is installed gh --version # Expected output: gh version X.X.X (YYYY-MM-DD) # If not installed, install it first, then authenticate gh auth login # Follow the prompts to authenticate with GitHub
-
Verify repository access:
# Check current repository git remote -v # Expected output should show: origin https://github.com/hmislk/hmis.git # Test GitHub access gh repo view hmislk/hmis --json name # Expected output: {"name":"hmis"}
-
Ensure clean working directory:
# Check git status git status # Expected output: "nothing to commit, working tree clean" # If you have uncommitted changes, stash them: # git stash push -m "temporary stash before deployment"
Follow these steps EXACTLY in order:
Step 1: Switch to development branch
git checkout developmentExpected output: Switched to branch 'development' or Already on 'development'
Step 2: Get latest changes
git pull origin developmentExpected output: Should show files updated or Already up to date.
Step 3: Push to QA1 deployment branch
git push origin development:hims-qa1 --forceExpected output: Should show something like:
To https://github.com/hmislk/hmis.git
+ abc1234...def5678 development -> hims-qa1 (forced update)
Step 4: Get the deployment run ID
gh run list --branch hims-qa1 --limit 1Expected output format:
STATUS TITLE WORKFLOW BRANCH EVENT ID ELAPSED AGE
in_progress Deploy to QA1 QA1 Environment CI-CD Workflow hims-qa1 push 1234567890 30s 1m
Copy the ID number (e.g., 1234567890) for the next step
Step 5: Monitor deployment (REPLACE [RUN_ID] with actual ID from step 4)
gh run watch [RUN_ID]Example: gh run watch 1234567890
Step 6: Verify deployment success Wait for the workflow to complete (shows ✓ symbols). Then test the application:
curl -s -o /dev/null -w "%{http_code}" https://qa.carecode.org/qa1/faces/index1.xhtmlExpected output: 200 (means success)
IMPORTANT: QA2 requires pull requests due to branch protection rules
Follow these steps EXACTLY in order:
Step 1: Switch to development branch
git checkout developmentExpected output: Switched to branch 'development' or Already on 'development'
Step 2: Get latest changes
git pull origin developmentExpected output: Should show files updated or Already up to date.
Step 3: Create pull request for QA2
gh pr create --base hims-qa2 --head development --title "Deploy latest development to QA2" --body "Automated deployment of latest development branch to QA2 environment"Expected output: A URL like https://github.com/hmislk/hmis/pull/14401
Copy the PR number from the URL (e.g., 14401)
Step 4: Merge the pull request (REPLACE [PR_NUMBER] with actual number from step 3)
gh pr merge [PR_NUMBER] --mergeExample: gh pr merge 14401 --merge
Expected output: ✓ Merged pull request #14401
Step 5: Get the deployment run ID
gh run list --branch hims-qa2 --limit 1Expected output format:
STATUS TITLE WORKFLOW BRANCH EVENT ID ELAPSED AGE
in_progress Deploy to QA2 HIMS QA-2 Environment CI-CD Workflow hims-qa2 push 1234567890 30s 1m
Copy the ID number (e.g., 1234567890) for the next step
Step 6: Monitor deployment (REPLACE [RUN_ID] with actual ID from step 5)
gh run watch [RUN_ID]Example: gh run watch 1234567890
Step 7: Verify deployment success Wait for the workflow to complete (shows ✓ symbols). Then test the application:
curl -s -o /dev/null -w "%{http_code}" https://qa.carecode.org/qa2/faces/index1.xhtmlExpected output: 200 (means success)
IMPORTANT: QA3 requires pull requests due to branch protection rules
Follow these steps EXACTLY in order:
Step 1: Switch to development branch
git checkout developmentExpected output: Switched to branch 'development' or Already on 'development'
Step 2: Get latest changes
git pull origin developmentExpected output: Should show files updated or Already up to date.
Step 3: Create pull request for QA3
gh pr create --base hims-qa3 --head development --title "Deploy latest development to QA3" --body "Automated deployment of latest development branch to QA3 environment"Expected output: A URL like https://github.com/hmislk/hmis/pull/14402
Copy the PR number from the URL (e.g., 14402)
Step 4: Merge the pull request (REPLACE [PR_NUMBER] with actual number from step 3)
gh pr merge [PR_NUMBER] --mergeExample: gh pr merge 14402 --merge
Expected output: ✓ Merged pull request #14402
Step 5: Get the deployment run ID
gh run list --branch hims-qa3 --limit 1Expected output format:
STATUS TITLE WORKFLOW BRANCH EVENT ID ELAPSED AGE
in_progress Deploy to QA3 HIMS QA-3 Environment CI-CD Workflow hims-qa3 push 1234567890 30s 1m
Copy the ID number (e.g., 1234567890) for the next step
Step 6: Monitor deployment (REPLACE [RUN_ID] with actual ID from step 5)
gh run watch [RUN_ID]Example: gh run watch 1234567890
Step 7: Verify deployment success Wait for the workflow to complete (shows ✓ symbols). Then test the application:
curl -s -o /dev/null -w "%{http_code}" https://qa.carecode.org/qa3/faces/index1.xhtmlExpected output: 200 (means success)
- Code Checkout: Latest code from the target branch
- Java Setup: JDK 11 with Temurin distribution
- Maven Cache: Caches dependencies for faster builds
- JDBC Configuration: Updates persistence.xml with environment-specific datasources
- Maven Build:
mvn clean package -DskipTests - Artifact Archive: Stores the generated WAR file
- Artifact Download: Gets the WAR file from build phase
- Server Connection: SSH connection to QA server
- Backup: Creates backup of existing WAR file
- File Transfer: Copies new WAR to server using rsync
- Payara Deployment:
- Undeploys existing application
- Deploys new WAR with force flag
- Sets correct context path
- Health Check: Validates application is running and reachable
- Cleanup: Removes temporary SSH keys
# List recent runs for a branch
gh run list --branch hims-qa1 --limit 5 # For QA1
gh run list --branch hims-qa2 --limit 5 # For QA2
gh run list --branch hims-qa3 --limit 5 # For QA3
# Watch a specific run in real-time
gh run watch [RUN_ID]
# View run details
gh run view [RUN_ID]- Go to https://github.com/hmislk/hmis/actions
- Filter by the deployment branch (hims-qa1, hims-qa2, or hims-qa3)
- Click on the most recent workflow run to see details
Error: gh: command not found
Solution:
# Install GitHub CLI first
# For Windows: winget install --id GitHub.cli
# For Mac: brew install gh
# For Linux: Follow https://github.com/cli/cli/blob/trunk/docs/install_linux.mdError: To authenticate, please run: gh auth login
Solution:
gh auth login
# Choose: GitHub.com > HTTPS > Y > Login with web browser
# Follow the browser promptsError: HTTP 403: Forbidden (HTTP 403)
Solution:
- Contact repository administrator for access
- Verify you're using the correct GitHub account
Symptoms:
- Deployment completes successfully but applications return 404 errors
curl https://qa.carecode.org/qa1/faces/index1.xhtmlreturns 404
Most Common Cause: Hardcoded JNDI datasources in persistence.xml
Solution:
-
Check persistence.xml configuration:
grep '<jta-data-source>' src/main/resources/META-INF/persistence.xml -
Expected output (CORRECT):
<jta-data-source>${JDBC_DATASOURCE}</jta-data-source> <jta-data-source>${JDBC_AUDIT_DATASOURCE}</jta-data-source>
-
If you see hardcoded values (INCORRECT):
<jta-data-source>jdbc/coop</jta-data-source> <jta-data-source>jdbc/ruhunuAudit</jta-data-source>
Fix immediately:
- Replace with environment variables
- Create PR with the fix
- Redeploy all affected QA environments
-
Verify build logs show proper replacement:
gh run view [RUN_ID] --log | grep "Update JDBC Data Sources"
Error: remote: error: GH013: Repository rule violations found
Solution: This is normal for protected branches. Use the Pull Request method instead.
Error: GraphQL: No commits between hims-qa3 and development
Solution: QA3 is already up to date. No deployment needed.
Symptoms: No GitHub Actions run appears after push Check these:
# Verify you pushed to correct branch
git ls-remote origin | grep hims-qa
# Check if workflow file exists
ls -la .github/workflows/*qa*.ymlSymptoms: Workflow fails or takes too long Actions:
# Check workflow logs
gh run view [RUN_ID] --log
# Check server status manually (if you have access)
# curl -I https://qa.carecode.org/qa1/faces/index1.xhtmlIf deployment fails:
-
Check the workflow status:
gh run list --branch hims-qa1 --limit 3
-
View detailed error logs:
gh run view [FAILED_RUN_ID] --log
-
If build failed, try again (often temporary):
# Wait 5 minutes, then retry the deployment git push origin development:hims-qa1 --force -
If deployment failed, check application manually:
curl -I https://qa.carecode.org/qa1/faces/index1.xhtml # If this returns 200, the app is working despite the workflow error
If a deployment fails or causes issues:
-
Check previous successful deployment:
gh run list --branch hims-qa1 --status success --limit 5
-
Redeploy from a previous commit:
# Find the commit hash from the successful deployment git push origin [COMMIT_HASH]:hims-qa1 --force -
Manual rollback on server:
- SSH to the QA server
- Use the backup WAR file:
mv qa1.war.old qa1.war - Redeploy using Payara asadmin
After successful deployment, applications will be available at:
- QA1: https://qa.carecode.org/qa1/faces/index1.xhtml
- QA2: https://qa.carecode.org/qa2/faces/index1.xhtml
- QA3: https://qa.carecode.org/qa3/faces/index1.xhtml
For complex deployment failures involving server infrastructure issues, see the comprehensive troubleshooting guide: 📋 QA Troubleshooting Guide
Common server-side issues include:
- EclipseLink DDL generation path errors
- Payara admin authentication failures
- Application state mismatches
- Missing server directories or files
- All server credentials are stored as GitHub repository secrets
- SSH keys are temporary and cleaned up after each deployment
- Database credentials are environment-specific and managed by the server configuration
# Deploy latest development to QA1 (Direct push)
git checkout development && git pull origin development
git push origin development:hims-qa1 --force
gh run list --branch hims-qa1 --limit 1
# Deploy latest development to QA2 (via PR - protected branch)
git checkout development && git pull origin development
gh pr create --base hims-qa2 --head development --title "Deploy to QA2" --body "Deploy latest development"
# Then merge the created PR via GitHub UI or: gh pr merge [PR_NUMBER] --merge
# Deploy latest development to QA3 (via PR - protected branch)
git checkout development && git pull origin development
gh pr create --base hims-qa3 --head development --title "Deploy to QA3" --body "Deploy latest development"
# Then merge the created PR via GitHub UI or: gh pr merge [PR_NUMBER] --merge
# Monitor deployment
gh run watch [RUN_ID]Copy and execute these commands one by one, checking each output:
[ ] gh --version
[ ] git status
[ ] git checkout development
[ ] git pull origin development
[ ] git push origin development:hims-qa1 --force
[ ] gh run list --branch hims-qa1 --limit 1
[ ] gh run watch [COPY_RUN_ID_HERE]
[ ] curl -s -o /dev/null -w "%{http_code}" https://qa.carecode.org/qa1/faces/index1.xhtml
Success criteria: Last command returns 200
Copy and execute these commands one by one, checking each output:
[ ] gh --version
[ ] git status
[ ] git checkout development
[ ] git pull origin development
[ ] gh pr create --base hims-qa2 --head development --title "Deploy latest development to QA2" --body "Automated deployment"
[ ] gh pr merge [COPY_PR_NUMBER_HERE] --merge
[ ] gh run list --branch hims-qa2 --limit 1
[ ] gh run watch [COPY_RUN_ID_HERE]
[ ] curl -s -o /dev/null -w "%{http_code}" https://qa.carecode.org/qa2/faces/index1.xhtml
Success criteria: Last command returns 200
Copy and execute these commands one by one, checking each output:
[ ] gh --version
[ ] git status
[ ] git checkout development
[ ] git pull origin development
[ ] gh pr create --base hims-qa3 --head development --title "Deploy latest development to QA3" --body "Automated deployment"
[ ] gh pr merge [COPY_PR_NUMBER_HERE] --merge
[ ] gh run list --branch hims-qa3 --limit 1
[ ] gh run watch [COPY_RUN_ID_HERE]
[ ] curl -s -o /dev/null -w "%{http_code}" https://qa.carecode.org/qa3/faces/index1.xhtml
Success criteria: Last command returns 200
If something goes wrong:
# Check recent workflow runs
gh run list --limit 5
# View error logs (replace RUN_ID)
gh run view [RUN_ID] --log
# Check if app is actually working
curl -I https://qa.carecode.org/qa1/faces/index1.xhtml
curl -I https://qa.carecode.org/qa2/faces/index1.xhtml
curl -I https://qa.carecode.org/qa3/faces/index1.xhtmlLast updated: 2025-07-31 This document is designed for both human operators and automated bots For questions or issues, contact the development team or create an issue in the HMIS repository.