ci: enhance pipeline with version persistence and direct deployment
Some checks failed
FHIR IG CI/CD Pipeline with Version Persistence / build-ig (push) Successful in 6m58s
FHIR IG CI/CD Pipeline with Version Persistence / deploy (push) Failing after 8s

- Add version extraction from IG and tag validation for releases
- Update package-list.json and package-feed.xml automatically on releases
- Replace Docker-based deployment with direct file upload via SCP/SSH
- Add publication request configuration for FHIR registry
- Remove obsolete Dockerfile.serve as deployment strategy changed
This commit is contained in:
jobayer
2025-12-22 12:58:59 +06:00
parent 18c7029f91
commit 3297b88035
5 changed files with 352 additions and 267 deletions

View File

@@ -1,14 +1,16 @@
name: FHIR IG CI/CD Pipeline name: FHIR IG CI/CD Pipeline with Version Persistence
on: on:
push: push:
branches: [ main, develop ] branches: [ main, develop ]
tags:
- 'v*.*.*' # Trigger on version tags like v0.3.0
pull_request: pull_request:
branches: [ main ] branches: [ main ]
env: env:
REGISTRY: git.dghs.gov.bd # Replace with your Gitea instance REGISTRY: git.dghs.gov.bd
IMAGE_NAME: gitadmin/bd-core-fhir-ig # Replace with your image name IMAGE_NAME: gitadmin/bd-core-fhir-ig
jobs: jobs:
build-ig: build-ig:
@@ -18,7 +20,38 @@ jobs:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v3 uses: actions/checkout@v3
with: with:
fetch-depth: 0 # Full history for proper IG building fetch-depth: 0
- name: Extract version from IG
id: version
run: |
# Extract version from ImplementationGuide resource
VERSION=$(grep -oP '<version value="\K[^"]+' input/bd.fhir.core.xml | head -1)
if [ -z "$VERSION" ]; then
echo "ERROR: Could not extract version from ImplementationGuide XML"
exit 1
fi
echo "Extracted version: $VERSION"
echo "version=$VERSION" >> $GITHUB_OUTPUT
# Determine if this is a release build (git tag) or dev build
if [[ "$GITHUB_REF" == refs/tags/v* ]]; then
BUILD_TYPE="release"
TAG_VERSION="${GITHUB_REF#refs/tags/v}"
# Verify tag matches IG version
if [ "$TAG_VERSION" != "$VERSION" ]; then
echo "ERROR: Git tag version ($TAG_VERSION) doesn't match IG version ($VERSION)"
exit 1
fi
else
BUILD_TYPE="dev"
fi
echo "build_type=$BUILD_TYPE" >> $GITHUB_OUTPUT
echo "Build type: $BUILD_TYPE"
- name: Install Docker CLI - name: Install Docker CLI
run: | run: |
@@ -26,47 +59,36 @@ jobs:
apt-get install -y docker.io apt-get install -y docker.io
docker --version docker --version
- name: Setup Docker Buildx - name: Build FHIR IG
uses: docker/setup-buildx-action@v3
with:
install: true
- name: Build FHIR IG (Copy In/Out)
run: | run: |
echo "Building FHIR IG using copy approach..." echo "Building FHIR IG version ${{ steps.version.outputs.version }}..."
# Create a container (don't start yet)
CONTAINER_ID=$(docker create \ CONTAINER_ID=$(docker create \
hl7fhir/ig-publisher-base:latest \ hl7fhir/ig-publisher-base:latest \
/bin/bash -c "cp -r /home/publisher/ig /tmp/build && cd /tmp/build && _updatePublisher.sh -y && _genonce.sh") /bin/bash -c "cp -r /home/publisher/ig /tmp/build && cd /tmp/build && _updatePublisher.sh -y && _genonce.sh")
echo "Container ID: $CONTAINER_ID" echo "Container ID: $CONTAINER_ID"
# Copy all source files into the container
docker cp $(pwd)/. $CONTAINER_ID:/home/publisher/ig/ docker cp $(pwd)/. $CONTAINER_ID:/home/publisher/ig/
# Start and wait for completion
docker start -a $CONTAINER_ID docker start -a $CONTAINER_ID
EXIT_CODE=$? EXIT_CODE=$?
# Copy outputs back # Copy outputs
echo "Copying outputs from container..." echo "Copying outputs from container..."
docker cp $CONTAINER_ID:/tmp/build/output ./output || echo "Warning: No output directory" docker cp $CONTAINER_ID:/tmp/build/output ./output || echo "Warning: No output directory"
docker cp $CONTAINER_ID:/tmp/build/fsh-generated ./fsh-generated || echo "No FSH generated files" docker cp $CONTAINER_ID:/tmp/build/fsh-generated ./fsh-generated || echo "No FSH generated"
docker cp $CONTAINER_ID:/tmp/build/input-cache ./input-cache || echo "No input-cache" docker cp $CONTAINER_ID:/tmp/build/input-cache ./input-cache || echo "No input-cache"
docker cp $CONTAINER_ID:/tmp/build/temp ./temp || echo "No temp directory" docker cp $CONTAINER_ID:/tmp/build/temp ./temp || echo "No temp directory"
# Show container logs if failed
if [ $EXIT_CODE -ne 0 ]; then if [ $EXIT_CODE -ne 0 ]; then
echo "Build failed, showing container logs:" echo "Build failed, showing logs:"
docker logs $CONTAINER_ID docker logs $CONTAINER_ID
docker rm $CONTAINER_ID
exit 1
fi fi
# Cleanup
docker rm $CONTAINER_ID docker rm $CONTAINER_ID
# Verify
if [ ! -f "output/index.html" ]; then if [ ! -f "output/index.html" ]; then
echo "ERROR: Build failed - no index.html" echo "ERROR: Build failed - no index.html"
exit 1 exit 1
@@ -74,210 +96,275 @@ jobs:
echo "✅ Build successful!" echo "✅ Build successful!"
- name: Verify IG Output - name: Update package-list.json and package-feed.xml for releases
if: steps.version.outputs.build_type == 'release'
run: | run: |
ls -la output/ VERSION="${{ steps.version.outputs.version }}"
if [ ! -f "output/index.html" ]; then DATE=$(date +%Y-%m-%d)
echo "ERROR: IG build failed - no index.html found" DATETIME=$(date -u +%Y-%m-%dT%H:%M:%SZ)
exit 1
# Update package-list.json and package-feed.xml
cat > update-registry-files.py << 'EOF'
import json
import sys
import xml.etree.ElementTree as ET
from datetime import datetime
version = sys.argv[1]
date = sys.argv[2]
datetime_iso = sys.argv[3]
# ========== Update package-list.json ==========
with open('package-list.json', 'r') as f:
pkg_list = json.load(f)
# Update current build path
for entry in pkg_list['list']:
if entry['version'] == 'current':
entry['path'] = 'https://fhir.dghs.gov.bd/core/'
break
# Check if this version already exists
version_exists = any(e['version'] == version for e in pkg_list['list'])
if not version_exists:
# Add new version entry
new_entry = {
"version": version,
"date": date,
"desc": f"Release {version}",
"path": f"https://fhir.dghs.gov.bd/core/{version}/",
"status": "trial-use",
"sequence": "STU 1"
}
# Insert after 'current' entry
pkg_list['list'].insert(1, new_entry)
else:
# Update existing entry
for entry in pkg_list['list']:
if entry['version'] == version:
entry['date'] = date
entry['path'] = f"https://fhir.dghs.gov.bd/core/{version}/"
break
with open('output/package-list.json', 'w') as f:
json.dump(pkg_list, f, indent=2)
print(f"✅ Updated package-list.json with version {version}")
# ========== Update package-feed.xml ==========
# Register namespaces
ET.register_namespace('', 'http://www.w3.org/2005/Atom')
# Parse existing feed
tree = ET.parse('package-feed.xml')
root = tree.getroot()
ns = {'atom': 'http://www.w3.org/2005/Atom'}
# Update feed updated timestamp
updated_elem = root.find('atom:updated', ns)
if updated_elem is not None:
updated_elem.text = datetime_iso
# Check if entry for this version already exists
entry_exists = False
for entry in root.findall('atom:entry', ns):
title = entry.find('atom:title', ns)
if title is not None and version in title.text:
entry_exists = True
# Update existing entry timestamp
entry_updated = entry.find('atom:updated', ns)
if entry_updated is not None:
entry_updated.text = datetime_iso
break
# If entry doesn't exist, create new one
if not entry_exists:
new_entry = ET.Element('{http://www.w3.org/2005/Atom}entry')
title = ET.SubElement(new_entry, '{http://www.w3.org/2005/Atom}title')
title.text = f"bd.fhir.core version {version}"
link = ET.SubElement(new_entry, '{http://www.w3.org/2005/Atom}link')
link.set('rel', 'alternate')
link.set('href', f"https://fhir.dghs.gov.bd/core/{version}/")
entry_id = ET.SubElement(new_entry, '{http://www.w3.org/2005/Atom}id')
entry_id.text = f"https://fhir.dghs.gov.bd/core/{version}/"
entry_updated = ET.SubElement(new_entry, '{http://www.w3.org/2005/Atom}updated')
entry_updated.text = datetime_iso
summary = ET.SubElement(new_entry, '{http://www.w3.org/2005/Atom}summary')
summary.text = f"Release {version} of Bangladesh Core FHIR Implementation Guide"
# Insert new entry at the beginning (after feed metadata)
# Find the position after the last feed-level element
insert_pos = 0
for i, child in enumerate(root):
if child.tag.endswith('entry'):
insert_pos = i
break
insert_pos = i + 1
root.insert(insert_pos, new_entry)
# Write updated feed
tree.write('output/package-feed.xml', encoding='utf-8', xml_declaration=True)
print(f"✅ Updated package-feed.xml with version {version}")
EOF
python3 update-registry-files.py "$VERSION" "$DATE" "$DATETIME"
# Copy updated files
cp output/package-list.json package-list.json
cp output/package-feed.xml package-feed.xml
echo "📋 Updated registry files (package-list.json and package-feed.xml)"
- name: Prepare deployment artifact
run: |
VERSION="${{ steps.version.outputs.version }}"
BUILD_TYPE="${{ steps.version.outputs.build_type }}"
# Create a tarball of the output
if [ "$BUILD_TYPE" == "release" ]; then
tar -czf ig-output.tar.gz -C output .
else
tar -czf ig-output.tar.gz -C output .
fi fi
echo "IG build successful!"
- name: Login to Gitea Container Registry echo "version=$VERSION" > deployment.env
if: github.ref == 'refs/heads/main' echo "build_type=$BUILD_TYPE" >> deployment.env
uses: docker/login-action@v3 echo "build_date=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> deployment.env
with:
registry: ${{ env.REGISTRY }}
username: ${{ gitea.actor }}
password: ${{ secrets.ACCESS_TOKEN_GITEA }}
- name: Extract metadata ls -lh ig-output.tar.gz
if: github.ref == 'refs/heads/main'
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=sha,prefix={{branch}}-
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push Docker image - name: Upload artifact
if: github.ref == 'refs/heads/main' uses: actions/upload-artifact@v3
uses: docker/build-push-action@v6
with: with:
context: . name: ig-output
file: ./Dockerfile.serve path: |
push: true ig-output.tar.gz
tags: ${{ steps.meta.outputs.tags }} deployment.env
labels: ${{ steps.meta.outputs.labels }} package-list.json
# cache-from: type=gha package-feed.xml
# cache-to: type=gha,mode=max retention-days: 30
deploy: deploy:
needs: build-ig needs: build-ig
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' if: (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))
steps: steps:
- name: Checkout repository - name: Download artifact
uses: actions/checkout@v3 uses: actions/download-artifact@v3
with:
name: ig-output
- name: Load deployment env
id: deploy_info
run: |
source deployment.env
echo "version=$version" >> $GITHUB_OUTPUT
echo "build_type=$build_type" >> $GITHUB_OUTPUT
echo "build_date=$build_date" >> $GITHUB_OUTPUT
echo "Deploying version: $version"
echo "Build type: $build_type"
- name: Deploy to server - name: Deploy to server
uses: appleboy/ssh-action@v1.0.3 uses: appleboy/scp-action@v0.1.7
env: with:
REGISTRY: ${{ env.REGISTRY }} host: ${{ secrets.DEPLOY_HOST }}
IMAGE_NAME: ${{ env.IMAGE_NAME }} username: ${{ secrets.DEPLOY_USER }}
IMAGE_TAG: latest password: ${{ secrets.DEPLOY_PASSWORD }}
port: ${{ secrets.DEPLOY_PORT || 22 }}
source: "ig-output.tar.gz,deployment.env,package-list.json,package-feed.xml"
target: "/tmp/fhir-ig-deploy/"
- name: Execute deployment on server
uses: appleboy/ssh-action@v1.0.3
with: with:
host: ${{ secrets.DEPLOY_HOST }} host: ${{ secrets.DEPLOY_HOST }}
username: ${{ secrets.DEPLOY_USER }} username: ${{ secrets.DEPLOY_USER }}
password: ${{ secrets.DEPLOY_PASSWORD }} password: ${{ secrets.DEPLOY_PASSWORD }}
port: ${{ secrets.DEPLOY_PORT || 22 }} port: ${{ secrets.DEPLOY_PORT || 22 }}
envs: REGISTRY,IMAGE_NAME,IMAGE_TAG
script: | script: |
# Create deployment directory if it doesn't exist
mkdir -p /opt/fhir-ig
cd /opt/fhir-ig
# Create docker-compose.prod.yml
cat > docker-compose.prod.yml << EOF
services:
fhir-ig:
image: \${REGISTRY}/\${IMAGE_NAME}:\${IMAGE_TAG:-latest}
container_name: fhir-ig-app
restart: unless-stopped
ports:
- "80:80"
environment:
- NODE_ENV=production
networks:
- fhir-ig-network
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
volumes:
- fhir-ig-logs:/var/log/nginx
networks:
fhir-ig-network:
driver: bridge
volumes:
fhir-ig-logs:
driver: local
EOF
# Create deployment script
cat > deploy.sh << 'DEPLOY_SCRIPT'
#!/bin/bash
set -e set -e
# Configuration # Load deployment info
COMPOSE_FILE="docker-compose.prod.yml" source /tmp/fhir-ig-deploy/deployment.env
SERVICE_NAME="fhir-ig"
BACKUP_DIR="/opt/backups/fhir-ig"
LOG_FILE="/var/log/fhir-ig-deploy.log"
# Create directories echo "=========================================="
mkdir -p "$BACKUP_DIR" echo "Deploying FHIR IG"
mkdir -p "$(dirname "$LOG_FILE")" echo "Version: $version"
echo "Build Type: $build_type"
echo "Build Date: $build_date"
echo "=========================================="
# Logging function # Create version directory structure
log() { VERSIONS_DIR="/opt/fhir-ig/versions"
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE" mkdir -p "$VERSIONS_DIR"
}
log "Starting deployment of BD Core FHIR IG..." # Determine target directory
log "Registry: $REGISTRY" if [ "$build_type" == "release" ]; then
log "Image: $IMAGE_NAME" TARGET_DIR="$VERSIONS_DIR/$version"
log "Tag: $IMAGE_TAG" echo "📦 Deploying release version to: $TARGET_DIR"
else
# Login to registry TARGET_DIR="$VERSIONS_DIR/dev"
echo "$GITEA_PASSWORD" | docker login $REGISTRY -u "$GITEA_USERNAME" --password-stdin echo "🔧 Deploying dev build to: $TARGET_DIR"
# Backup current container if it exists
if docker compose -f "$COMPOSE_FILE" ps --services --filter "status=running" | grep -q "$SERVICE_NAME"; then
log "Creating backup of current deployment..."
BACKUP_FILE="$BACKUP_DIR/backup-$(date +%Y%m%d-%H%M%S).tar.gz"
docker compose -f "$COMPOSE_FILE" exec -T "$SERVICE_NAME" tar -czf - -C /usr/share/nginx/html . > "$BACKUP_FILE" 2>/dev/null || log "Backup failed, continuing..."
fi fi
# Set environment variables for docker compose # Create target directory
export REGISTRY="$REGISTRY" mkdir -p "$TARGET_DIR"
export IMAGE_NAME="$IMAGE_NAME"
export IMAGE_TAG="$IMAGE_TAG"
# Pull the latest image # Extract IG output
log "Pulling latest image: $REGISTRY/$IMAGE_NAME:$IMAGE_TAG..." echo "Extracting IG output..."
docker pull "$REGISTRY/$IMAGE_NAME:$IMAGE_TAG" tar -xzf /tmp/fhir-ig-deploy/ig-output.tar.gz -C "$TARGET_DIR"
# docker pull "\${REGISTRY}/\${IMAGE_NAME}:\${IMAGE_TAG}" # Copy package-list.json to root
cp /tmp/fhir-ig-deploy/package-list.json "$VERSIONS_DIR/package-list.json"
# Stop and remove old container # Copy package-feed.xml to root
log "Stopping old container..." cp /tmp/fhir-ig-deploy/package-feed.xml "$VERSIONS_DIR/package-feed.xml"
docker compose -f "$COMPOSE_FILE" down || log "No existing container to stop"
# Start new container # Update 'current' symlink for releases
log "Starting new container..." if [ "$build_type" == "release" ]; then
docker compose -f "$COMPOSE_FILE" up -d echo "Updating 'current' symlink to point to $version"
rm -f "$VERSIONS_DIR/current"
ln -sf "$version" "$VERSIONS_DIR/current"
fi
# Wait for container to be healthy # Ensure nginx container is running with correct config
# log "Waiting for container to become healthy..." cd /opt/fhir-ig
# timeout=120
# elapsed=0
# healthy=false
# while [ $elapsed -lt $timeout ]; do # Download deployment files if they don't exist
# if docker compose -f "$COMPOSE_FILE" ps --format json | grep -q '"Health":"healthy"'; then if [ ! -f "docker-compose.prod.yml" ]; then
# log "Container is healthy!" echo "ERROR: docker-compose.prod.yml not found!"
# healthy=true echo "Please deploy the updated docker-compose.prod.yml and nginx.conf first"
# break exit 1
# fi fi
# sleep 5
# elapsed=$((elapsed + 5))
# log "Waiting... ($elapsed/$timeout seconds)"
# done
# if [ "$healthy" = false ]; then # Restart nginx to pick up new content
# log "ERROR: Container failed to become healthy within $timeout seconds" docker compose -f docker-compose.prod.yml restart fhir-ig || \
# docker compose -f "$COMPOSE_FILE" logs --tail=50 docker compose -f docker-compose.prod.yml up -d
# log "Rolling back..."
# docker compose -f "$COMPOSE_FILE" down
# exit 1
# fi
# Cleanup old images (keep last 3 versions) # Cleanup
log "Cleaning up old images..." rm -rf /tmp/fhir-ig-deploy
docker images "\${REGISTRY}/\${IMAGE_NAME}" --format "table {{.Repository}}:{{.Tag}}\t{{.CreatedAt}}" | tail -n +2 | sort -k2 -r | tail -n +4 | awk '{print $1}' | xargs -r docker rmi || log "No old images to clean"
# Cleanup old backups (keep only last 5) echo "=========================================="
log "Cleaning up old backups..." echo "✅ Deployment completed successfully!"
ls -t "$BACKUP_DIR"/backup-*.tar.gz 2>/dev/null | tail -n +6 | xargs -r rm || log "No old backups to clean" echo "Version $version is now available at:"
if [ "$build_type" == "release" ]; then
echo " - https://fhir.dghs.gov.bd/core/$version/"
echo " - https://fhir.dghs.gov.bd/core/ (current)"
else
echo " - https://fhir.dghs.gov.bd/core/dev/"
fi
echo "=========================================="
log "Deployment completed successfully!" # List all versions
log "🌐 Service available at: http://$(hostname -I | awk '{print $1}')" echo "Available versions:"
ls -lh "$VERSIONS_DIR" | grep -v total
# Display final status
docker compose -f "$COMPOSE_FILE" ps
DEPLOY_SCRIPT
# Make deploy script executable
chmod +x deploy.sh
# Set registry credentials
export GITEA_USERNAME="${{ gitea.actor }}"
export GITEA_PASSWORD="${{ secrets.ACCESS_TOKEN_GITEA }}"
# Execute deployment
./deploy.sh

View File

@@ -1,42 +0,0 @@
# Multi-stage build for serving FHIR IG output
FROM nginx:alpine
# Copy the built IG output to nginx html directory
# (Uncomment and adjust the path if needed)
COPY output/ /usr/share/nginx/html/
# Copy custom nginx configuration
COPY nginx.conf /etc/nginx/nginx.conf
# Create a non-root user for security
RUN addgroup -g 1001 -S nginx-user && \
adduser -S -D -H -u 1001 -h /var/cache/nginx -s /sbin/nologin -G nginx-user -g nginx-user nginx-user
# Set proper permissions for Nginx directories
RUN chown -R nginx-user:nginx-user /usr/share/nginx/html && \
chown -R nginx-user:nginx-user /var/cache/nginx && \
chown -R nginx-user:nginx-user /var/log/nginx && \
chown -R nginx-user:nginx-user /etc/nginx/conf.d
# Fix Nginx PID permission issue
RUN mkdir -p /var/cache/nginx/run && \
chown -R nginx-user:nginx-user /var/cache/nginx/run
# Update nginx.conf to point PID to writable location
# Ensure your nginx.conf has:
# pid /var/cache/nginx/run/nginx.pid;
# Switch to non-root user
USER nginx-user
# Health check
# HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
# CMD curl -f http://localhost/ || exit 1
EXPOSE 80
# Start Nginx in foreground
# CMD ["nginx", "-g", "daemon off;"]
CMD ["nginx", "-g", "daemon off;", "-c", "/etc/nginx/nginx.conf"]

View File

@@ -0,0 +1,14 @@
{
"package-id": "bd.fhir.core",
"version": "0.2.0",
"path": "https://fhir.dghs.gov.bd/core/0.2.0",
"mode": "working",
"status": "trial-use",
"sequence": "STU1",
"desc": "First draft release of the Bangladesh Core FHIR Implementation Guide",
"descmd": "# Bangladesh Core FHIR IG - Release 0.2.0\n\nThis is the first draft release of the Bangladesh Core FHIR Implementation Guide. It defines national base profiles, value sets, and extensions for health data interoperability in Bangladesh.\n\n## Key Features\n- Base profiles for common FHIR resources\n- National value sets and code systems\n- Extensions for Bangladesh-specific requirements\n\n## Status\nThis is a trial-use release. Implementers are encouraged to provide feedback.",
"first": true,
"category": "National Base",
"ci-build": "https://fhir.dghs.gov.bd/core/",
"package-list": "https://fhir.dghs.gov.bd/core/package-list.json"
}

View File

@@ -1,30 +1,33 @@
<rss xmlns:atom="http://www.w3.org/2005/Atom" <?xml version="1.0" encoding="UTF-8"?>
xmlns:content="http://purl.org/rss/1.0/modules/content/" <feed xmlns="http://www.w3.org/2005/Atom">
xmlns:dc="http://purl.org/dc/elements/1.1/" <id>https://fhir.dghs.gov.bd/core/package-feed.xml</id>
xmlns:fhir="http://hl7.org/fhir/feed" version="2.0"> <title>Bangladesh Core FHIR IG Package Feed</title>
<channel> <subtitle>FHIR Package Feed for bd.fhir.core</subtitle>
<title>Bangladesh Core FHIR Packages</title> <link rel="self" href="https://fhir.dghs.gov.bd/core/package-feed.xml"/>
<description>New Packages published by DGHS Bangladesh</description> <link rel="alternate" href="https://fhir.dghs.gov.bd/core/"/>
<link>https://git.dghs.gov.bd/gitadmin/BD-Core-FHIR-IG</link> <updated>2025-10-02T00:00:00Z</updated>
<generator>DGHS Bangladesh FHIR Publication tooling</generator> <author>
<lastBuildDate>Thu, 02 Oct 2025 12:00:00 +0000</lastBuildDate> <name>MIS, Directorate General of Health Services (DGHS), Bangladesh</name>
<atom:link href="https://git.dghs.gov.bd/gitadmin/BD-Core-FHIR-IG/src/branch/main/package-feed.xml" <uri>https://dghs.gov.bd</uri>
rel="self" type="application/rss+xml"/> </author>
<pubDate>Thu, 02 Oct 2025 12:00:00 +0000</pubDate>
<language>en</language>
<ttl>600</ttl>
<item> <!-- Entries will be automatically added by the CI/CD pipeline -->
<title>bd.fhir.core#0.2.0</title> <!-- Example entry structure (will be generated): -->
<description>The first draft release of the Bangladesh Core FHIR Implementation Guide.</description> <!--
<link>https://git.dghs.gov.bd/gitadmin/BD-Core-FHIR-IG/releases/download/v0.2.0/bd.fhir.core-0.2.0.tgz</link> <entry>
<guid isPermaLink="true">https://git.dghs.gov.bd/gitadmin/BD-Core-FHIR-IG/releases/download/v0.2.0/bd.fhir.core-0.2.0.tgz</guid> <title>bd.fhir.core version 0.2.0</title>
<dc:creator>DGHS Bangladesh</dc:creator> <link rel="alternate" href="https://fhir.dghs.gov.bd/core/0.2.0/"/>
<fhir:version>4.0.1</fhir:version> <id>https://fhir.dghs.gov.bd/core/0.2.0/</id>
<fhir:kind>IG</fhir:kind> <updated>2025-10-02T00:00:00Z</updated>
<pubDate>Thu, 02 Oct 2025 12:00:00 +0000</pubDate> <summary>Release 0.2.0 of Bangladesh Core FHIR Implementation Guide</summary>
<fhir:details>Publication run at 02/10/2025 by DGHS Bangladesh using IG Publisher. Source: BD-Core-FHIR-IG repo</fhir:details> </entry>
</item> -->
</channel> <entry>
</rss> <title>bd.fhir.core version 0.2.0</title>
<link rel="alternate" href="https://fhir.dghs.gov.bd/core/0.2.0/"/>
<id>https://fhir.dghs.gov.bd/core/0.2.0/</id>
<updated>2025-10-02T00:00:00Z</updated>
<summary>First draft release of Bangladesh Core FHIR Implementation Guide</summary>
</entry>
</feed>

23
package-list.json Normal file
View File

@@ -0,0 +1,23 @@
{
"package-id": "bd.fhir.core",
"title": "Bangladesh Core FHIR Implementation Guide",
"canonical": "https://fhir.dghs.gov.bd/core/",
"introduction": "The Bangladesh Core FHIR IG defines national base profiles, value sets, and extensions for health data interoperability.",
"list": [
{
"version": "current",
"desc": "Continuous Integration Build (latest in development)",
"path": "https://fhir.dghs.gov.bd/core/",
"status": "ci-build",
"current": true
},
{
"version": "0.2.0",
"date": "2025-10-02",
"desc": "First draft release of the Bangladesh Core FHIR IG",
"path": "https://fhir.dghs.gov.bd/core/0.2.0/",
"status": "trial-use",
"sequence": "STU 1"
}
]
}