Skip to content

github

Github workflow examples and instructions for OIDC authentication with Optum AWS accounts and SaaS Artifactory integration.

IDE:
claude
codex
vscode
Version:
0.0.0

applyTo: '**/*' description: 'GitHub Actions workflows and EPL (Enterprise Platform Library) integration patterns for Optum development with comprehensive examples for all supported languages and technologies.'

GitHub Actions & EPL Workflows Instructions

Core Requirements

Required Runner

Always utilize uhg-runner for successful GitHub interactions due to security and IP whitelisting.

Required Authentication

  • See artifactory.instructions.md for SaaS Artifactory authentication setup
  • See aws-oidc.instructions.md for OIDC authentication setup

EPL Workflow Patterns

All EPL workflows follow the reusable workflow pattern from uhg-pipelines/ci-workflows@v2. The standard structure includes:

Standard Workflow Template

name: [Language] CI

on:
  workflow_dispatch:
  pull_request:
    branches: [main]
    types: [opened, reopened, synchronize, ready_for_review]
    paths: [.github/workflows/your-workflow.yml, your-app-path/**]
  push:
    branches: ["release/**", main]
    paths: [.github/workflows/your-workflow.yml, your-app-path/**]

# Cancel currently running workflow if we get a new commit
concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true

jobs:
  build-and-quality-scans:
    uses: uhg-pipelines/ci-workflows/.github/workflows/[language]-ci.yml@v2
    with:
      # Required parameters
      jfrog-project-key: your-project-key
      # Language-specific parameters

Language-Specific EPL Workflows

Node.js Applications

NPM Workflow

name: Node NPM CI

on:
  workflow_dispatch:
  pull_request:
    branches: [main]
    types: [opened, reopened, synchronize, ready_for_review]
    paths: [.github/workflows/node-npm-ci.yml, src/**]
  push:
    branches: ["release/**", main]
    paths: [.github/workflows/node-npm-ci.yml, src/**]

concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true

jobs:
  node-ci-reusable:
    uses: uhg-pipelines/ci-workflows/.github/workflows/node-npm-ci.yml@v2
    with:
      # Required
      jfrog-project-key: your-project-key
      docker-tags: centraluhg.jfrog.io/your-project-docker-np-loc/your-app:1.0.${{ github.run_number }}
      
      # Optional
      docker-context: '.'
      docker-dockerfile: 'Dockerfile'
      working-directory: '.'
      node-version: "20"
      upload-artifacts-name: 'node-artifacts'
      upload-artifacts-include-hidden: true
      upload-artifacts-path: |
        coverage/lcov.info
        dist/

Yarn Workflow

jobs:
  node-ci-reusable:
    uses: uhg-pipelines/ci-workflows/.github/workflows/node-yarn-ci.yml@v2
    with:
      jfrog-project-key: your-project-key
      docker-tags: centraluhg.jfrog.io/your-project-docker-np-loc/your-app:1.0.${{ github.run_number }}
      docker-context: '.'
      docker-dockerfile: 'Dockerfile'
      working-directory: '.'
      node-version: "20"

PNPM Workflow

jobs:
  node-ci-reusable:
    uses: uhg-pipelines/ci-workflows/.github/workflows/node-pnpm-ci.yml@v2
    with:
      jfrog-project-key: your-project-key
      docker-tags: centraluhg.jfrog.io/your-project-docker-np-loc/your-app:1.0.${{ github.run_number }}
      docker-context: '.'
      docker-dockerfile: 'Dockerfile'
      working-directory: '.'
      node-version: "20"

Python Applications

Pip Workflow

name: Python Pip CI

on:
  workflow_dispatch:
  pull_request:
    branches: [main]
    types: [opened, reopened, synchronize, ready_for_review]
    paths: [.github/workflows/python-pip-ci.yml, src/**]
  push:
    branches: ['release/**', main]
    paths: [.github/workflows/python-pip-ci.yml, src/**]

concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true

jobs:
  build-and-quality-scans:
    uses: uhg-pipelines/ci-workflows/.github/workflows/python-pip-ci.yml@v2
    with:
      # Required
      jfrog-project-key: your-project-key
      docker-tags: centraluhg.jfrog.io/your-project-docker-np-loc/your-app:1.0.${{ github.run_number }}
      
      # Optional
      docker-context: '.'
      docker-dockerfile: 'Dockerfile'
      working-directory: '.'
      source-dir: 'src'
      test-dir: 'tests'
      artifact-upload: true

Poetry Workflow

jobs:
  build-and-quality-scans:
    uses: uhg-pipelines/ci-workflows/.github/workflows/python-poetry-ci.yml@v2
    with:
      jfrog-project-key: your-project-key
      docker-tags: centraluhg.jfrog.io/your-project-docker-np-loc/your-app:1.0.${{ github.run_number }}
      docker-context: '.'
      docker-dockerfile: 'Dockerfile'
      working-directory: '.'
      python-version: "3.11"

Java Applications

Maven Workflow

name: Java Maven CI

on:
  workflow_dispatch:
  pull_request:
    branches: [main]
    types: [opened, reopened, synchronize, ready_for_review]
    paths: [.github/workflows/java-maven-ci.yml, src/**]
  push:
    branches: ['release/**', main]
    paths: [.github/workflows/java-maven-ci.yml, src/**]

concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true

jobs:
  build-and-quality-scans:
    uses: uhg-pipelines/ci-workflows/.github/workflows/java-maven-ci.yml@v2
    with:
      # Required
      jfrog-project-key: your-project-key
      docker-tags: centraluhg.jfrog.io/your-project-docker-np-loc/your-app:1.0.${{ github.run_number }}
      
      # Optional
      docker-context: '.'
      docker-dockerfile: 'Dockerfile'
      working-directory: '.'
      upload-artifacts-name: 'java-maven-artifacts'
      upload-artifacts-include-hidden: true
      upload-artifacts-path: |
        target/

Gradle Workflow

jobs:
  build-and-quality-scans:
    uses: uhg-pipelines/ci-workflows/.github/workflows/java-gradle-ci.yml@v2
    with:
      jfrog-project-key: your-project-key
      docker-tags: centraluhg.jfrog.io/your-project-docker-np-loc/your-app:1.0.${{ github.run_number }}
      docker-context: '.'
      docker-dockerfile: 'Dockerfile'
      working-directory: '.'
      java-version: "17"
      java-distribution: "temurin"

.NET Applications

name: Dotnet CI

on:
  workflow_dispatch:
  pull_request:
    branches: [main]
    types: [opened, reopened, synchronize, ready_for_review]
    paths: [.github/workflows/dotnet-ci.yml, src/**]
  push:
    branches: ['release/**', main]
    paths: [.github/workflows/dotnet-ci.yml, src/**]

concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true

jobs:
  build-and-quality-scans:
    uses: uhg-pipelines/ci-workflows/.github/workflows/dotnet-ci.yml@v2
    with:
      # Required
      jfrog-project-key: your-project-key
      
      # Optional
      docker-context: '.'
      docker-dockerfile: 'Dockerfile'
      docker-tags: centraluhg.jfrog.io/your-project-docker-np-loc/your-app:1.0.${{ github.run_number }}
      working-directory: '.'
      dotnet-publish: true
      dotnet-publish-project-path: src/YourApp/YourApp.csproj
      dotnet-version: 8.0.x
      dotnet-pack-args: "/p:PackageVersion=1.2.${{ github.run_number }}"

Go Applications

name: Golang CI

on:
  workflow_dispatch:
  pull_request:
    branches: [main]
    types: [opened, reopened, synchronize, ready_for_review]
    paths: [.github/workflows/go-ci.yml, src/**]
  push:
    branches: ["release/**", main]
    paths: [.github/workflows/go-ci.yml, src/**]

concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true

jobs:
  build-and-quality-scans:
    uses: uhg-pipelines/ci-workflows/.github/workflows/go-ci.yml@v2
    with:
      # Required
      jfrog-project-key: your-project-key
      docker-tags: centraluhg.jfrog.io/your-project-docker-np-loc/your-app:1.0.${{ github.run_number }}
      
      # Optional
      docker-context: '.'
      docker-dockerfile: 'Dockerfile'
      working-directory: '.'
      go-deploy: true
      go-private-orgs: github.com/uhg-internal

Scala SBT Applications

name: Scala SBT CI

on:
  workflow_dispatch:
  pull_request:
    branches: [main]
    types: [opened, reopened, synchronize, ready_for_review]
    paths: [.github/workflows/scala-sbt-ci.yml, src/**]
  push:
    branches: ['release/**', main]
    paths: [.github/workflows/scala-sbt-ci.yml, src/**]

concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true

jobs:
  get-version:
    runs-on: uhg-runner
    steps:
      - name: Checkout Code
        uses: actions/checkout@v4
      - name: Get Version
        id: get-version
        uses: uhg-pipelines/epl-version/generate-manifest-tag@v1
        with:
          version-type: date-sha
    outputs:
      version: ${{ steps.get-version.outputs.docker-tag }}

  build-and-quality-scans:
    needs: get-version
    uses: uhg-pipelines/ci-workflows/.github/workflows/scala-sbt-ci.yml@v2
    with:
      jfrog-project-key: your-project-key
      docker-tags: centraluhg.jfrog.io/your-project-docker-np-loc/your-app:${{ needs.get-version.outputs.version }}
      docker-context: '.'
      docker-dockerfile: 'Dockerfile'
      working-directory: '.'
      java-version: "11"
      java-distribution: temurin
      sbt-build-jvm-args: -Xmx2g -XX:+UseG1GC
      sbt-build-command: clean test stage
      sbt-publish-command: publish
      publish-version: ${{ needs.get-version.outputs.version }}

Docker-Only Applications

name: Docker CI

on:
  workflow_dispatch:
  pull_request:
    branches: [main]
    types: [opened, reopened, synchronize, ready_for_review]
    paths: [.github/workflows/docker-ci.yml, Dockerfile, src/**]
  push:
    branches: ['release/**', main]
    paths: [.github/workflows/docker-ci.yml, Dockerfile, src/**]

concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true

jobs:
  docker-build-and-scans:
    uses: uhg-pipelines/ci-workflows/.github/workflows/docker-ci.yml@v2
    with:
      # Required
      jfrog-project-key: your-project-key
      docker-tags: centraluhg.jfrog.io/your-project-docker-np-loc/your-app:1.0.${{ github.run_number }}
      
      # Optional
      docker-context: '.'
      docker-dockerfile: 'Dockerfile'

Terraform Provider

name: Terraform Provider CI

on:
  workflow_dispatch:
  pull_request:
    branches: [main]
    types: [opened, reopened, synchronize, ready_for_review]
    paths: [.github/workflows/terraform-provider-ci.yml, src/**]
  push:
    branches: ["release/**", main]
    paths: [.github/workflows/terraform-provider-ci.yml, src/**]

concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true

jobs:
  build-and-quality-scans:
    uses: uhg-pipelines/ci-workflows/.github/workflows/terraform-provider-ci.yml@v2
    with:
      # Required
      jfrog-project-key: your-project-key
      
      # Optional
      working-directory: '.'
      tf-provider-deploy: "true"

Common Parameters

Required Parameters

  • jfrog-project-key: Your JFrog project identifier (e.g., your-team-project)
  • docker-tags: Container image tags for publishing

Optional Parameters

  • docker-context: Build context directory (default: .)
  • docker-dockerfile: Dockerfile path (default: Dockerfile)
  • working-directory: Working directory for commands (default: .)

Language-Specific Parameters

Node.js

  • node-version: Node.js version (default varies by workflow)
  • upload-artifacts-name: Artifact bundle name
  • upload-artifacts-include-hidden: Include hidden files in artifacts
  • upload-artifacts-path: Files to upload as artifacts

Python

  • python-version: Python version
  • source-dir: Source code directory
  • test-dir: Test directory
  • artifact-upload: Enable artifact upload

Java

  • java-version: Java version
  • java-distribution: Java distribution (e.g., temurin)

.NET

  • dotnet-version: .NET version
  • dotnet-publish: Enable publishing
  • dotnet-publish-project-path: Project file path
  • dotnet-pack-args: Additional pack arguments

Go

  • go-deploy: Enable deployment
  • go-private-orgs: Private Go module organizations

Scala

  • sbt-build-jvm-args: JVM arguments for SBT
  • sbt-build-command: SBT build command
  • sbt-publish-command: SBT publish command
  • publish-version: Version for publishing

Best Practices

Workflow Configuration

  1. Use uhg-runner: Always specify runs-on: uhg-runner
  2. Concurrency Control: Include concurrency groups to cancel redundant builds
  3. Path Filters: Use specific paths to trigger builds only when relevant files change
  4. Version Pinning: Use @v2 or specific version tags for reusable workflows

Security & Compliance

  1. OIDC Authentication: Follow authentication patterns in referenced instruction files
  2. Golden Images: Use only Optum-approved container base images
  3. Secret Management: Never hardcode secrets in workflows

Performance Optimization

  1. Selective Triggers: Use path-based triggering to avoid unnecessary builds
  2. Caching: Leverage built-in caching in EPL workflows
  3. Parallel Jobs: Structure workflows for maximum parallelization

Troubleshooting

Common Issues

  1. Authentication Failures: Check Artifactory setup and project key
  2. Build Failures: Verify working directory and file paths
  3. Permission Issues: Ensure proper runner and repository permissions

Debugging Steps

  1. Check workflow logs in GitHub Actions UI
  2. Verify file paths and working directories
  3. Confirm JFrog project key is correct
  4. Review authentication setup

Reference Repository

Complete examples available at: https://github.com/uhg-pipelines/ci-workflows-demos