Skip to content

Test actions

Test actions #619

Workflow file for this run

name: Test actions
on:
pull_request:
branches: [trunk]
paths:
- '.github/workflows/test-actions.yml'
- '**/action.yml'
- '!README.md'
workflow_dispatch:
inputs:
runner:
description: 'Runner'
required: true
default: 'elvia-runner'
type: 'string'
env:
APPLICATION_BASE_NAME: 'demo-api'
SYSTEM_NAME: 'core'
jobs:
prepare-jobs:
name: Prepare jobs
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrices.outputs.matrix }}
matrix-analyze: ${{ steps.set-matrices.outputs.matrix-analyze }}
matrix-build: ${{ steps.set-matrices.outputs.matrix-build }}
matrix-deploy: ${{ steps.set-matrices.outputs.matrix-deploy }}
matrix-trivy: ${{ steps.set-matrices.outputs.matrix-trivy }}
all-changed-files: ${{ steps.changed-files.outputs.all_changed_files }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set matrices
id: set-matrices
run: |
# Default matrix
echo "matrix={\"runner\":[\"$RUNNER\"]}" >> "$GITHUB_OUTPUT"
# Analyze matrix
{
echo 'matrix-analyze<<EOF'
cat << EOF
{
"runner": ["$RUNNER"],
"language": ["csharp","go","python"]
}
EOF
echo EOF
} >> "$GITHUB_OUTPUT"
# Build matrix
{
echo 'matrix-build<<EOF'
cat << EOF
{
"runner": ["$RUNNER","ubuntu-latest"],
"project-file": [
"applications/demo-api/demo-api/core-demo-api.csproj",
"applications/demo-api-go/go.mod",
"applications/demo-api-go/Dockerfile",
"applications/demo-api-python/pyproject.toml"
],
"registry": ["","ghcr.io/3lvia"],
"include": [
{
"application-name": "${{ env.APPLICATION_BASE_NAME }}-go"
},
{
"application-name": "${{ env.APPLICATION_BASE_NAME }}",
"project-file": "applications/demo-api/demo-api/core-demo-api.csproj"
},
{
"application-name": "${{ env.APPLICATION_BASE_NAME }}-python",
"project-file": "applications/demo-api-python/pyproject.toml"
}
]
}
EOF
echo EOF
} >> "$GITHUB_OUTPUT"
# Deploy matrix
{
echo 'matrix-deploy<<EOF'
cat << EOF
{
"runner": ["$RUNNER","ubuntu-latest"],
"application-name": [
"${{ env.APPLICATION_BASE_NAME }}",
"${{ env.APPLICATION_BASE_NAME }}-go",
"${{ env.APPLICATION_BASE_NAME }}-python"
],
"runtime-cloud-provider": ["AKS","GKE"],
"include": [
{
"helm-values-file": ".github/deploy/values-demo-api.yml"
},
{
"application-name": "${{ env.APPLICATION_BASE_NAME }}-go",
"helm-values-file": ".github/deploy/values-demo-api-go.yml"
},
{
"application-name": "${{ env.APPLICATION_BASE_NAME }}-go",
"helm-values-file": ".github/deploy/values-demo-api-python.yml"
},
]
}
EOF
echo EOF
} >> "$GITHUB_OUTPUT"
# Trivy matrix
{
echo 'matrix-trivy<<EOF'
cat << EOF
{
"runner": ["$RUNNER","ubuntu-latest"]
}
EOF
echo EOF
} >> "$GITHUB_OUTPUT"
env:
RUNNER: ${{ github.event_name == 'workflow_dispatch' && inputs.runner || 'elvia-runner' }}
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v45
- name: Print changed files
run: echo '${{ steps.changed-files.outputs.all_changed_files }}'
analyze:
name: Analyze
needs: [prepare-jobs]
strategy:
matrix: ${{ fromJson(needs.prepare-jobs.outputs.matrix-analyze) }}
concurrency:
group: '${{ github.workflow_ref }}-${{ matrix.runner }}-${{ matrix.language }}-analyze'
cancel-in-progress: true
runs-on: ${{ matrix.runner }}
permissions:
actions: read
contents: read
security-events: write
if: ${{ github.event_name != 'pull_request' || contains(needs.prepare-jobs.outputs.all-changed-files, 'analyze/action.yml') }}
steps:
- name: Checkout this repository
uses: actions/checkout@v4
- name: Get GitHub App token
uses: actions/create-github-app-token@v1
id: app-token
with:
app-id: ${{ vars.GH_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
- name: Checkout core repository
uses: actions/checkout@v4
with:
repository: '3lvia/core'
token: ${{ steps.app-token.outputs.token }}
path: 'core'
- uses: ./analyze
with:
checkout: 'false'
language: ${{ matrix.language }}
working-directory: 'core/applications'
unit-tests:
name: Unit Tests
needs: [prepare-jobs]
strategy:
matrix: ${{ fromJson(needs.prepare-jobs.outputs.matrix) }}
concurrency:
group: '${{ github.workflow_ref }}-${{ matrix.runner }}-unit-tests'
cancel-in-progress: true
runs-on: ${{ matrix.runner }}
permissions:
contents: read
checks: write
issues: read
pull-requests: write
if: ${{ github.event_name != 'pull_request' || contains(needs.prepare-jobs.outputs.all-changed-files, 'unittest/action.yml') }}
steps:
- name: Checkout this repository
uses: actions/checkout@v4
- name: Get GitHub App token
uses: actions/create-github-app-token@v1
id: app-token
with:
app-id: ${{ vars.GH_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
- name: Checkout core repository
uses: actions/checkout@v4
with:
repository: '3lvia/core'
token: ${{ steps.app-token.outputs.token }}
path: 'core'
- uses: ./unittest
with:
checkout: 'false'
working-directory: 'core/applications/demo-api'
build:
name: Build
needs: [prepare-jobs]
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.prepare-jobs.outputs.matrix-build) }}
concurrency:
group: |
${{ github.workflow_ref }}-${{ matrix.runner }}-${{ matrix.application-name }}-${{ matrix.project-file }}-${{ matrix.registry }}
cancel-in-progress: true
runs-on: ${{ matrix.runner }}
permissions:
actions: read
contents: write
id-token: write
packages: write # Required for publishing to GitHub Container Registry
pull-requests: write
security-events: write
environment: build
# Integration tests depend on deploy which depends on build, so we need to run build if integration tests have changed.
if: ${{ github.event_name != 'pull_request' || contains(needs.prepare-jobs.outputs.all-changed-files, 'build/action.yml') || contains(needs.prepare-jobs.outputs.all-changed-files, 'integrationtest/action.yml') }}
steps:
- name: Checkout this repository
uses: actions/checkout@v4
- name: Get GitHub App token
uses: actions/create-github-app-token@v1
id: app-token
with:
app-id: ${{ vars.GH_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
- name: Checkout core repository
uses: actions/checkout@v4
with:
repository: '3lvia/core'
token: ${{ steps.app-token.outputs.token }}
path: 'core'
- uses: ./build
with:
checkout: 'false'
name: ${{ matrix.application-name }}
namespace: ${{ env.SYSTEM_NAME }}
project-file: 'core/${{ matrix.project-file }}'
docker-additional-tags: 'v42,v1.2.3'
registry: ${{ matrix.registry }}
trivy-upload-report: 'true'
trivy-post-comment: 'true'
AZURE_CLIENT_ID: ${{ vars.ACR_CLIENT_ID }}
build-vulnerable-service:
name: Build Vulnerable Service
needs: [prepare-jobs]
concurrency:
group: '${{ github.workflow_ref }}-build-vulnerable-service'
cancel-in-progress: true
runs-on: elvia-runner
permissions:
actions: read
contents: write
pull-requests: write
security-events: write
environment: build
# We are testing if a PR comment is created, so ony run on PR.
if: ${{ github.event_name == 'pull_request' && contains(needs.prepare-jobs.outputs.all-changed-files, 'build/action.yml') }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Create Dockerfile with vulnerabilities
run: |
cat << EOF > Dockerfile
FROM debian:10
ENTRYPOINT ["echo", "I am vulnerable"]
EOF
- uses: ./build
with:
checkout: 'false'
name: 'vulnerable-service'
namespace: ${{ env.SYSTEM_NAME }}
project-file: 'Dockerfile'
severity: 'CRITICAL,HIGH'
registry: 'ghcr.io/3lvia'
trivy-upload-report: 'true'
trivy-post-comment: 'true'
push: 'false'
continue-on-error: true
- name: Check that pull request comment was created
run: |
result=$(gh pr view \
-R '${{ github.repository }}' \
'${{ github.event.pull_request.number }}' \
--json comments \
-q '.comments | .[] | select(.author.login == "github-actions" and (.body | contains("<!-- vulnerable-service -->\n# :warning: Vulnerabilities detected in")))')
if [[ -n "$result" ]]; then
echo "Pull request comment was created successfully!"
else
echo "Pull request comment was not created."
exit 1
fi
env:
GH_TOKEN: ${{ github.token }}
deploy-dev:
name: Deploy Dev
needs: [prepare-jobs, build]
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.prepare-jobs.outputs.matrix-deploy) }}
concurrency:
group: '${{ github.workflow_ref }}-${{ matrix.application-name }}-${{ matrix.runtime-cloud-provider }}-deploy-dev'
cancel-in-progress: false
runs-on: ${{ matrix.runner }}
permissions:
contents: read
id-token: write
environment: dev
# Changes in build might affect deploy, so we test deploy as well if build has changed.
# Also, since integration tests are run after deploy, we need to run deploy if integration tests have changed.
if: ${{ github.event_name != 'pull_request' || contains(needs.prepare-jobs.outputs.all-changed-files, 'build/action.yml') || contains(needs.prepare-jobs.outputs.all-changed-files, 'deploy/action.yml') || contains(needs.prepare-jobs.outputs.all-changed-files, 'integrationtest/action.yml') }}
steps:
- name: Checkout this repository
uses: actions/checkout@v4
- name: Get GitHub App token
uses: actions/create-github-app-token@v1
id: app-token
with:
app-id: ${{ vars.GH_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
- name: Checkout core repository
uses: actions/checkout@v4
with:
repository: '3lvia/core'
token: ${{ steps.app-token.outputs.token }}
path: 'core'
- uses: ./deploy
with:
checkout: 'false'
name: ${{ matrix.application-name }}
namespace: ${{ env.SYSTEM_NAME }}
environment: 'dev'
helm-values-file: 'core/.github/deploy/values-${{ matrix.application-name }}.yml'
slack-channel: '#team-core-alerts-muted'
runtime-cloud-provider: ${{ matrix.runtime-cloud-provider }}
AZURE_CLIENT_ID: ${{ vars.AKS_CLIENT_ID }}
GC_SERVICE_ACCOUNT: ${{ vars.GC_SERVICE_ACCOUNT }}
GC_WORKLOAD_IDENTITY_PROVIDER: ${{ vars.GC_WORKLOAD_IDENTITY_PROVIDER }}
integration-tests:
name: Integration Tests
needs: [prepare-jobs, deploy-dev]
strategy:
matrix: ${{ fromJson(needs.prepare-jobs.outputs.matrix) }}
concurrency:
group: '${{ github.workflow_ref }}-${{ matrix.runner }}-integration-tests'
cancel-in-progress: true
runs-on: ${{ matrix.runner }}
permissions:
contents: read
checks: write
issues: read
pull-requests: write
id-token: write
if: ${{ github.event_name != 'pull_request' || contains(needs.prepare-jobs.outputs.all-changed-files, 'integrationtest/action.yml') }}
steps:
- name: Checkout this repository
uses: actions/checkout@v4
- name: Get GitHub App token
uses: actions/create-github-app-token@v1
id: app-token
with:
app-id: ${{ vars.GH_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
- name: Checkout core repository
uses: actions/checkout@v4
with:
repository: '3lvia/core'
token: ${{ steps.app-token.outputs.token }}
path: 'core'
- uses: ./integrationtest
with:
checkout: 'false'
system: ${{ env.SYSTEM_NAME }}
working-directory: 'core/applications/demo-api'
env:
BASE_URL: 'https://core.dev-elvia.io/demo-api'
trivy-iac-scan:
name: Trivy IaC Scan
needs: [prepare-jobs]
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.prepare-jobs.outputs.matrix-trivy) }}
concurrency:
group: '${{ github.workflow_ref }}-${{ matrix.runner }}-trivy-iac-scan'
cancel-in-progress: true
runs-on: ${{ matrix.runner }}
permissions:
actions: read
contents: read
security-events: write
if: ${{ github.event_name != 'pull_request' || contains(needs.prepare-jobs.outputs.all-changed-files, 'trivy-iac-scan/action.yml') }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- uses: ./trivy-iac-scan
with:
checkout: 'false'
terraform-format:
name: Terraform Format
needs: [prepare-jobs]
strategy:
matrix: ${{ fromJson(needs.prepare-jobs.outputs.matrix) }}
concurrency:
group: '${{ github.workflow_ref }}-${{ matrix.runner }}-terraform-format'
cancel-in-progress: true
runs-on: ${{ matrix.runner }}
if: ${{ github.event_name != 'pull_request' || contains(needs.prepare-jobs.outputs.all-changed-files, 'terraform-format/action.yml') }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- uses: ./terraform-format
with:
checkout: 'false'
slack-message-vault:
name: Slack Message using Vault
needs: [prepare-jobs]
strategy:
matrix: ${{ fromJson(needs.prepare-jobs.outputs.matrix) }}
concurrency:
group: '${{ github.workflow }}-${{ github.event_name }}-${{ matrix.runner }}-slack-message-vault'
cancel-in-progress: true
runs-on: ${{ matrix.runner }}
permissions:
contents: read
id-token: write
if: ${{ github.event_name != 'pull_request' || contains(needs.prepare-jobs.outputs.all-changed-files, 'slack-message/action.yml') }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- uses: ./slack-message
with:
slack-channel: '#team-core-alerts-muted'
message: ':test_tube: Testing Slack Message using Vault in ${{ github.workflow }} for ${{ github.event_name }} event.'
environment: 'dev'
namespace: 'core'
slack-message-token:
name: Slack Message using token
needs: [prepare-jobs]
strategy:
matrix: ${{ fromJson(needs.prepare-jobs.outputs.matrix) }}
concurrency:
group: '${{ github.workflow }}-${{ github.event_name }}-${{ matrix.runner }}-slack-message-token'
cancel-in-progress: true
runs-on: ${{ matrix.runner }}
if: ${{ github.event_name != 'pull_request' || contains(needs.prepare-jobs.outputs.all-changed-files, 'slack-message/action.yml') }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- uses: ./slack-message
with:
slack-channel: '#team-core-alerts-muted'
message: ':test_tube: Testing Slack Message using token in ${{ github.workflow }} for ${{ github.event_name }} event.'
slack-api-token: ${{ secrets.SLACK_API_TOKEN }}
vault:
name: Vault
needs: [prepare-jobs]
strategy:
matrix: ${{ fromJson(needs.prepare-jobs.outputs.matrix) }}
concurrency:
group: '${{ github.workflow }}-${{ github.event_name }}-${{ matrix.runner }}-vault'
cancel-in-progress: true
runs-on: ${{ matrix.runner }}
permissions:
contents: read
id-token: write
if: ${{ github.event_name != 'pull_request' || contains(needs.prepare-jobs.outputs.all-changed-files, 'vault/action.yml') }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- uses: ./vault
with:
environment: 'dev'
system: 'core'
secrets: |
core/kv/data/info/appinsights/core name | APP_INSIGHTS_NAME
- name: Check that secret was fetched successfully
run: |
if [[ -z '${{ env.APP_INSIGHTS_NAME }}' ]]; then
echo 'Secret was not fetched.'
exit 1
else
echo 'Secret was fetched successfully!'
fi