From 5ea7f50e613121219fc5ed92fdf773874f84f8d1 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 18 Nov 2025 20:22:02 +0000 Subject: [PATCH] Add release version and commit links to footer with GitHub releases This commit implements the following enhancements: 1. **Footer Display Changes:** - Added release version link (e.g., v1.0.0) pointing to GitHub releases page - Kept existing commit hash link for easy access to specific commits - Both links now visible in the footer build info section 2. **Environment Configuration:** - Added version field to all environment files (prod, staging, alpha, dev) - VERSION_PLACEHOLDER added for build-time replacement in prod/staging/alpha - Local dev environment uses '1.0.0-dev' for development 3. **Jenkins Pipeline Updates:** - Updated Build App stage to replace VERSION_PLACEHOLDER with BASE_VERSION - Added new "Create GitHub Release" stage for main branch deployments - Release creation includes: * Checks if release already exists to prevent duplicates * Creates annotated git tag (e.g., v1.0.0) * Pushes tag to GitHub * Creates GitHub release via API with deployment metadata - Requires 'github-pat' credential in Jenkins 4. **Component & Test Updates:** - Updated FooterComponent to include version and githubReleaseUrl - Added comprehensive tests for version link rendering - Updated existing tests to verify both release and commit links This enables users to easily navigate to both the specific release version and individual commits from the application footer. --- Jenkinsfile | 83 +++++++++++++++++-- .../components/footer/footer.component.html | 1 + .../footer/footer.component.spec.ts | 17 ++++ .../app/components/footer/footer.component.ts | 2 + .../src/environments/environment.alpha.ts | 1 + .../src/environments/environment.prod.ts | 1 + .../src/environments/environment.staging.ts | 1 + elohim-app/src/environments/environment.ts | 1 + 8 files changed, 99 insertions(+), 8 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 1e4887d6d..5a100a4e3 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -213,16 +213,20 @@ BRANCH_NAME=${env.BRANCH_NAME}""" withBuildVars(props) { echo 'Building Angular application' + echo "Using base version: ${BASE_VERSION}" echo "Using git hash: ${GIT_COMMIT_HASH}" echo "Using image tag: ${IMAGE_TAG}" - + // Replace placeholders sh """ + sed -i "s/VERSION_PLACEHOLDER/${BASE_VERSION}/g" src/environments/environment.prod.ts + sed -i "s/VERSION_PLACEHOLDER/${BASE_VERSION}/g" src/environments/environment.staging.ts + sed -i "s/VERSION_PLACEHOLDER/${BASE_VERSION}/g" src/environments/environment.alpha.ts sed -i "s/GIT_HASH_PLACEHOLDER/${GIT_COMMIT_HASH}/g" src/environments/environment.prod.ts sed -i "s/GIT_HASH_PLACEHOLDER/${GIT_COMMIT_HASH}/g" src/environments/environment.staging.ts sed -i "s/GIT_HASH_PLACEHOLDER/${GIT_COMMIT_HASH}/g" src/environments/environment.alpha.ts """ - + sh 'npm run build' sh 'ls -la dist/' } @@ -780,10 +784,10 @@ BRANCH_NAME=${env.BRANCH_NAME}""" container('builder'){ script { def props = loadBuildVars() - + withBuildVars(props) { echo "Deploying to Production: ${IMAGE_TAG}" - + // Validate configmap sh ''' kubectl get configmap elohim-config-prod -n ethosengine || { @@ -791,15 +795,15 @@ BRANCH_NAME=${env.BRANCH_NAME}""" exit 1 } ''' - + // Deploy - + // Update deployment manifest - sh "sed 's/BUILD_NUMBER_PLACEHOLDER/${IMAGE_TAG}/g' manifests/prod-deployment.yaml > manifests/prod-deployment-${IMAGE_TAG}.yaml" + sh "sed 's/BUILD_NUMBER_PLACEHOLDER/${IMAGE_TAG}/g' manifests/prod-deployment.yaml > manifests/prod-deployment-${IMAGE_TAG}.yaml" sh "kubectl apply -f manifests/prod-deployment-${IMAGE_TAG}.yaml" sh "kubectl rollout restart deployment/elohim-site -n ethosengine" sh 'kubectl rollout status deployment/elohim-site -n ethosengine --timeout=300s' - + echo 'Production deployment completed!' } } @@ -807,6 +811,69 @@ BRANCH_NAME=${env.BRANCH_NAME}""" } } + stage('Create GitHub Release') { + when { + branch 'main' + } + steps { + container('builder'){ + script { + def props = loadBuildVars() + + withBuildVars(props) { + echo "Creating GitHub release for version: v${BASE_VERSION}" + + withCredentials([usernamePassword(credentialsId: 'github-pat', passwordVariable: 'GITHUB_TOKEN', usernameVariable: 'GITHUB_USERNAME')]) { + sh """#!/bin/bash + set -euo pipefail + + # Configure git + git config --global --add safe.directory "*" + + # Check if release already exists + RELEASE_EXISTS=\$(curl -s -o /dev/null -w "%{http_code}" \\ + -H "Authorization: token \${GITHUB_TOKEN}" \\ + "https://api.github.com/repos/ethosengine/elohim/releases/tags/v${BASE_VERSION}") + + if [ "\$RELEASE_EXISTS" = "200" ]; then + echo "Release v${BASE_VERSION} already exists, skipping creation" + exit 0 + fi + + # Create annotated tag + git tag -a "v${BASE_VERSION}" -m "Release version ${BASE_VERSION}" ${GIT_COMMIT_HASH} || { + echo "Tag v${BASE_VERSION} may already exist locally, continuing..." + } + + # Push tag to GitHub + git push https://\${GITHUB_TOKEN}@github.com/ethosengine/elohim.git "v${BASE_VERSION}" || { + echo "Tag push failed, may already exist remotely" + } + + # Create release via GitHub API + RELEASE_NOTES="## Release v${BASE_VERSION}\\n\\nDeployed to production on \$(date -u +"%Y-%m-%d %H:%M:%S UTC")\\n\\n**Commit:** ${GIT_COMMIT_HASH}\\n**Image Tag:** ${IMAGE_TAG}" + + curl -X POST \\ + -H "Authorization: token \${GITHUB_TOKEN}" \\ + -H "Accept: application/vnd.github.v3+json" \\ + "https://api.github.com/repos/ethosengine/elohim/releases" \\ + -d "{\\ + \\"tag_name\\": \\"v${BASE_VERSION}\\",\\ + \\"name\\": \\"Release v${BASE_VERSION}\\",\\ + \\"body\\": \\"\${RELEASE_NOTES}\\",\\ + \\"draft\\": false,\\ + \\"prerelease\\": false\\ + }" + + echo "✅ GitHub release v${BASE_VERSION} created successfully" + """ + } + } + } + } + } + } + stage('Cleanup') { steps { container('builder'){ diff --git a/elohim-app/src/app/components/footer/footer.component.html b/elohim-app/src/app/components/footer/footer.component.html index 1bdfd6d30..63868a511 100644 --- a/elohim-app/src/app/components/footer/footer.component.html +++ b/elohim-app/src/app/components/footer/footer.component.html @@ -56,6 +56,7 @@
+ v{{ version }} {{ gitHash }}
diff --git a/elohim-app/src/app/components/footer/footer.component.spec.ts b/elohim-app/src/app/components/footer/footer.component.spec.ts index ac93b8fc3..e2a19912a 100644 --- a/elohim-app/src/app/components/footer/footer.component.spec.ts +++ b/elohim-app/src/app/components/footer/footer.component.spec.ts @@ -24,15 +24,32 @@ describe('FooterComponent', () => { expect(component).toBeTruthy(); }); + it('should initialize version from environment', () => { + expect(component.version).toBe(environment.version); + }); + it('should initialize gitHash from environment', () => { expect(component.gitHash).toBe(environment.gitHash); }); + it('should construct githubReleaseUrl with version', () => { + const expectedUrl = `https://github.com/ethosengine/elohim/releases/v${environment.version}`; + expect(component.githubReleaseUrl).toBe(expectedUrl); + }); + it('should construct githubCommitUrl with gitHash', () => { const expectedUrl = `https://github.com/ethosengine/elohim/commit/${environment.gitHash}`; expect(component.githubCommitUrl).toBe(expectedUrl); }); + it('should render release version link in template', () => { + const compiled = fixture.nativeElement; + const releaseLink = compiled.querySelector('[data-cy="release-version"]'); + expect(releaseLink).toBeTruthy(); + expect(releaseLink.textContent.trim()).toBe(`v${environment.version}`); + expect(releaseLink.getAttribute('href')).toBe(component.githubReleaseUrl); + }); + it('should render git hash link in template', () => { const compiled = fixture.nativeElement; const gitHashLink = compiled.querySelector('[data-cy="git-hash"]'); diff --git a/elohim-app/src/app/components/footer/footer.component.ts b/elohim-app/src/app/components/footer/footer.component.ts index e0b528655..2e4944799 100644 --- a/elohim-app/src/app/components/footer/footer.component.ts +++ b/elohim-app/src/app/components/footer/footer.component.ts @@ -9,6 +9,8 @@ import { environment } from '../../../environments/environment'; styleUrl: './footer.component.css' }) export class FooterComponent { + version = environment.version; gitHash = environment.gitHash; + githubReleaseUrl = `https://github.com/ethosengine/elohim/releases/v${environment.version}`; githubCommitUrl = `https://github.com/ethosengine/elohim/commit/${environment.gitHash}`; } diff --git a/elohim-app/src/environments/environment.alpha.ts b/elohim-app/src/environments/environment.alpha.ts index 0034e141d..d01267ab7 100644 --- a/elohim-app/src/environments/environment.alpha.ts +++ b/elohim-app/src/environments/environment.alpha.ts @@ -2,5 +2,6 @@ export const environment = { production: false, logLevel: 'debug' as 'debug' | 'info' | 'error', environment: 'alpha', + version: 'VERSION_PLACEHOLDER', gitHash: 'GIT_HASH_PLACEHOLDER' }; diff --git a/elohim-app/src/environments/environment.prod.ts b/elohim-app/src/environments/environment.prod.ts index 29ed20fba..3e773c119 100644 --- a/elohim-app/src/environments/environment.prod.ts +++ b/elohim-app/src/environments/environment.prod.ts @@ -2,5 +2,6 @@ export const environment = { production: true, logLevel: 'error' as 'debug' | 'info' | 'error', environment: 'production', + version: 'VERSION_PLACEHOLDER', gitHash: 'GIT_HASH_PLACEHOLDER' }; \ No newline at end of file diff --git a/elohim-app/src/environments/environment.staging.ts b/elohim-app/src/environments/environment.staging.ts index 8841fa256..f7163eb33 100644 --- a/elohim-app/src/environments/environment.staging.ts +++ b/elohim-app/src/environments/environment.staging.ts @@ -2,5 +2,6 @@ export const environment = { production: false, logLevel: 'debug' as 'debug' | 'info' | 'error', environment: 'staging', + version: 'VERSION_PLACEHOLDER', gitHash: 'GIT_HASH_PLACEHOLDER' }; \ No newline at end of file diff --git a/elohim-app/src/environments/environment.ts b/elohim-app/src/environments/environment.ts index 2d046de58..ac030fe46 100644 --- a/elohim-app/src/environments/environment.ts +++ b/elohim-app/src/environments/environment.ts @@ -2,5 +2,6 @@ export const environment = { production: false, logLevel: 'debug' as 'debug' | 'info' | 'error', environment: 'development', + version: '1.0.0-dev', gitHash: 'local-dev' }; \ No newline at end of file