Popular Conditional Commands for CI/CD
Mastering Conditional Logic in GitHub Actions: Practical If-Else Patterns for CI/CD
Building Robust CI/CD Pipelines with Conditional Steps in GitHub Actions
Status Check Functions: success(), failure(), always(), and cancelled() in GitHub Actions for ci cd/setup
Popular Conditional Commands for CI/CD
# 1. Continue on error for a step (GitHub Actions)
- name: Run tests
run: npm test
continue-on-error: true
# 2. Continue on error for a job (GitHub Actions)
jobs:
build:
runs-on: ubuntu-latest
continue-on-error: true
steps:
- run: make build
# 3. Always run a step, even if previous steps failed (GitHub Actions)
- name: Upload logs
run: ./upload-logs.sh
if: always()
# 4. Only run if previous steps succeeded
- name: Deploy
run: ./deploy.sh
if: success()
# 5. Only run if previous steps failed
- name: Notify on failure
run: ./notify-failure.sh
if: failure()
# 6. Run on success or failure (Azure Pipelines)
- task: PublishTestResults@2
condition: succeededOrFailed()
# 7. Continue on error for a task (Azure Pipelines)
- task: SomeTask@1
continueOnError: true
# 8. Custom condition using variables (Azure Pipelines)
- script: echo "Conditional step"
condition: eq(variables['Build.SourceBranch'], 'refs/heads/main')
# 9. Run only on pull requests
- name: PR Check
run: ./pr-check.sh
if: github.event_name == 'pull_request'
# 10. Run only on main branch
- name: Main branch deploy
run: ./deploy-main.sh
if: github.ref == 'refs/heads/main'
# 11. Skip step if previous failed
- name: Lint
run: npm run lint
if: success()
# 12. Run only if a matrix job failed (GitHub Actions)
- name: Matrix failure handler
run: ./handle-failure.sh
if: failure() && matrix.os == 'ubuntu-latest'
# 13. Continue on error in reusable workflow (GitHub Actions)
jobs:
test:
uses: ./.github/workflows/reusable-test.yml
continue-on-error: true
# 14. Run step only if a previous job succeeded with issues (Azure Pipelines)
- job: B
dependsOn: A
condition: eq(dependencies.A.result,'SucceededWithIssues')
steps:
- script: echo "Job B ran"
# 15. Run step only if a file changed (GitHub Actions)
- name: Run if src changed
run: ./src-changed.sh
if: contains(github.event.head_commit.message, 'src')
# 16. Timeout for a step (GitHub Actions)
- name: Long running task
run: ./long-task.sh
timeout-minutes: 10
# 17. Run only if environment variable is set
- name: Run if ENV is set
run: ./run-if-env.sh
if: env.MY_ENV_VAR != ''
# 18. Continue on error for deployment (Azure Pipelines)
- task: AzureRmWebAppDeployment@4
continueOnError: true
# 19. Run step only if previous step was skipped
- name: Handle skipped
run: ./handle-skipped.sh
if: skipped()
# 20. Run only if previous steps were canceled
- name: Handle cancel
run: ./handle-cancel.sh
if: cancelled()
# 21. Run a step only if a previous step succeeded (GitHub Actions)
- name: Build Docker image
run: docker build -t myapp .
if: steps.test.outcome == 'success'
# 22. Run a step only if a previous step failed (GitHub Actions)
- name: Debug on test failure
run: ./debug.sh
if: steps.test.outcome == 'failure'
# 23. Run a job only if another job failed (GitHub Actions)
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: ./build.sh
notify:
needs: build
runs-on: ubuntu-latest
if: needs.build.result == 'failure'
steps:
- run: ./notify.sh
# 24. Run a step only for tagged commits
- name: Deploy tagged release
run: ./deploy-release.sh
if: startsWith(github.ref, 'refs/tags/')
# 25. Skip a step if a specific file was not changed
- name: Build docs if docs changed
run: ./build-docs.sh
if: contains(github.event.head_commit.message, 'docs/')
# 26. Run a step only if a secret is available
- name: Publish if secret exists
run: ./publish.sh
if: env.MY_SECRET != ''
# 27. Continue on error for a matrix job (GitHub Actions)
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node: [12, 14, 16]
continue-on-error: ${{ matrix.node == 12 }}
steps:
- run: npm test
# 28. Run a step only on schedule event
- name: Scheduled maintenance
run: ./maintenance.sh
if: github.event_name == 'schedule'
# 29. Run a step only if a pull request is labeled "urgent"
- name: Urgent PR action
run: ./urgent-action.sh
if: contains(github.event.pull_request.labels.*.name, 'urgent')
# 30. Run a step only if a previous step was cancelled
- name: Handle cancellation
run: ./cancel-handler.sh
if: cancelled()
# 31. Run a step only if a commit message contains a keyword
- name: Run if message contains [deploy]
run: ./deploy.sh
if: contains(github.event.head_commit.message, '[deploy]')
# 32. Run a step only if an environment variable matches a value
- name: Run for production
run: ./prod-task.sh
if: env.ENVIRONMENT == 'production'
# 33. Run a step only if a job in another workflow succeeded (GitHub Actions with workflow_run)
on:
workflow_run:
workflows: ["Build"]
types:
- completed
jobs:
deploy:
if: github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-latest
steps:
- run: ./deploy.sh
# 34. Run a step only if a GitHub Actions input is true
- name: Run if input enabled
run: ./feature.sh
if: inputs.enableFeature == 'true'
# 35. Continue on error for a manual approval step (Azure Pipelines)
- task: ManualValidation@0
inputs:
notifyUsers: user@domain.com
continueOnError: true
Building Robust CI/CD Pipelines with Conditional Steps in GitHub Actions
Branch-Specific Build Matrix
name: Smart Matrix Build
on: [push]
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
include:
- os: ubuntu-latest
extra_checks: true
steps:
- uses: actions/checkout@v4
- name: Extended Security Scan
if: matrix.extra_checks
run: ./security-scan.sh
- PR Label-Based Deployment
name: Label-Triggered Deployment
on:
pull_request:
types: [labeled]
jobs:
deploy-preview:
if: contains(github.event.pull_request.labels.*.name, 'deploy-preview')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: ./deploy-preview-environment.sh
- Critical Path Optimizer
name: Critical Path Build
on: [push]
jobs:
impact-analysis:
runs-on: ubuntu-latest
outputs:
critical: ${{ steps.analyze.outputs.critical }}
steps:
- uses: actions/checkout@v4
- id: analyze
run: echo "critical=$(git diff --name-only HEAD^ | grep -q 'core/'; echo $?)" >> $GITHUB_OUTPUT
build:
needs: impact-analysis
if: needs.impact-analysis.outputs.critical == '0'
runs-on: ubuntu-latest
steps:
- run: ./build-critical-components.sh
- Rollback Automation
name: Auto-Rollback System
on:
workflow_run:
workflows: ["Production Deployment"]
types:
- completed
jobs:
rollback-check:
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v6
id: check-deployment
with:
script: |
const { data } = await github.rest.repos.listDeployments({
owner: context.repo.owner,
repo: context.repo.repo,
environment: 'production'
})
return data[0].statuses_url
execute-rollback:
needs: rollback-check
if: failure() && contains(needs.rollback-check.outputs.result, 'inactive')
runs-on: ubuntu-latest
steps:
- run: ./trigger-rollback.sh
- Cost-Optimized Nightly Builds
name: Nightly Efficiency
on:
schedule:
- cron: '0 22 * * 1-5' # 10PM UTC weekdays
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Lightweight Tests
run: ./run-fast-tests.sh
- name: Full Test Suite
if: github.event.schedule != '0 22 * * 1-5' # Only on manual triggers
run: ./run-full-tests.sh
- Environment-Aware Configuration
name: Contextual Config
on: [push]
jobs:
setup:
runs-on: ubuntu-latest
outputs:
env_config: ${{ steps.config.outputs.file }}
steps:
- name: Select Config
id: config
run: |
if [[ ${{ github.ref == 'refs/heads/main' }} ]]; then
echo "file=prod.yaml" >> $GITHUB_OUTPUT
else
echo "file=dev.yaml" >> $GITHUB_OUTPUT
fi
deploy:
needs: setup
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: ./deploy.sh --config ${{ needs.setup.outputs.env_config }}
- Hotfix Validation Gate
name: Hotfirex Guardian
on:
pull_request:
branches: [hotfix/**]
jobs:
emergency-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: ./validate-hotfix-urgency.sh
deploy:
needs: emergency-check
if: success() && contains(github.event.pull_request.title, '[CRITICAL]')
runs-on: ubuntu-latest
steps:
- run: ./expedited-deploy.sh
- Multi-Stage Approval Chain
name: Tiered Deployment
on:
workflow_dispatch:
inputs:
environment:
description: 'Target environment'
required: true
default: 'staging'
jobs:
staging-deploy:
if: github.event.inputs.environment == 'staging'
runs-on: ubuntu-latest
steps:
- run: ./deploy-staging.sh
production-approval:
needs: staging-deploy
if: github.event.inputs.environment == 'production'
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v6
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: 'Production deployment requires approval: [Approve](https://...)'
})
- Auto-Skip Documentation Builds
name: Doc Impact Filter
on: [push]
jobs:
check-docs:
runs-on: ubuntu-latest
outputs:
docs-only: ${{ steps.filter.outputs.docs }}
steps:
- uses: actions/checkout@v4
- id: filter
run: |
changed_files=$(git diff --name-only HEAD^)
if echo "$changed_files" | grep -qv '^docs/'; then
echo "docs-only=false" >> $GITHUB_OUTPUT
else
echo "docs-only=true" >> $GITHUB_OUTPUT
fi
build:
needs: check-docs
if: needs.check-docs.outputs.docs-only == 'false'
runs-on: ubuntu-latest
steps:
- run: ./build-system.sh
- Performance-Adaptive Testing
name: Intelligent Test Orchestration
on: [push]
jobs:
benchmark:
runs-on: ubuntu-latest
outputs:
test-profile: ${{ steps.analyze.outputs.profile }}
steps:
- uses: actions/checkout@v4
- id: analyze
run: |
complexity=$(cloc --json | jq '.SUM.comment_lines')
if (( complexity > 1000 )); then
echo "profile=extensive" >> $GITHUB_OUTPUT
else
echo "profile=basic" >> $GITHUB_OUTPUT
fi
test:
needs: benchmark
runs-on: ubuntu-latest
strategy:
matrix:
profile: [${{ needs.benchmark.outputs.test-profile }}]
steps:
- run: ./run-tests-${{ matrix.profile }}.sh
Status Check Functions: success(), failure(), always(), and cancelled() in GitHub Actions for ci cd/setup
Tri-State Notification System
name: Smart Notifications
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: ./build.sh
notify:
needs: build
runs-on: ubuntu-latest
steps:
- name: Success Alert
if: ${{ success() }}
run: ./slack-success.sh
- name: Failure Report
if: ${{ failure() }}
run: ./slack-failure.sh
- name: Cancellation Notice
if: ${{ cancelled() }}
run: ./slack-cancelled.sh
- Self-Cleaning Workspace
name: Auto-Clean Environment
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: ./run-tests.sh
- name: Clean Resources
if: ${{ always() }}
run: |
docker system prune -f
rm -rf ./temp
- Failure Forensics
name: Debug Assistant
on: [workflow_dispatch]
jobs:
analyze:
runs-on: ubuntu-latest
steps:
- run: ./flakey-process.sh
- name: Capture Core Dump
if: ${{ failure() }}
run: ./capture-core-dump.sh
- name: Upload Diagnostics
if: ${{ failure() }}
uses: actions/upload-artifact@v3
with:
name: failure-diagnostics
path: /tmp/dumps
- Cancellation-Aware Rollback
name: Graceful Termination
on: [workflow_run]
jobs:
rollback:
runs-on: ubuntu-latest
steps:
- name: Restore Backup
if: ${{ cancelled() }}
run: ./restore-previous-version.sh
- name: Log Cancellation
if: ${{ cancelled() }}
run: echo "Job $GITHUB_RUN_ID cancelled at $(date)" >> cancel.log
- Conditional Deployment Gates
name: Deployment Safeguards
on:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- run: ./run-all-tests.sh
deploy:
needs: test
if: ${{ success() }}
runs-on: ubuntu-latest
steps:
- run: ./deploy-prod.sh
- Stateful Artifact Handling
name: Smart Artifact Routing
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: ./build.sh
- run: exit 1 # Simulated failure
- name: Upload Success Artifact
if: ${{ success() }}
uses: actions/upload-artifact@v3
with:
name: success-build
path: ./dist
- name: Upload Failure Logs
if: ${{ failure() }}
uses: actions/upload-artifact@v3
with:
name: failure-logs
path: ./logs
- Parallel Outcome Processing
name: Distributed Status Handling
on: [workflow_run]
jobs:
job1:
runs-on: ubuntu-latest
steps:
- run: ./process-data.sh
success_handler:
needs: job1
if: ${{ success() }}
runs-on: ubuntu-latest
steps:
- run: ./handle-success.sh
failure_handler:
needs: job1
if: ${{ failure() }}
runs-on: ubuntu-latest
steps:
- run: ./handle-failure.sh
- Matrix Status Propagation
name: Cross-Platform Validation
on: [pull_request]
jobs:
test:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps:
- run: ./platform-tests.sh
report:
needs: test
runs-on: ubuntu-latest
if: ${{ contains(needs.test.result, 'failure') }}
steps:
- run: ./generate-cross-platform-report.sh
- Approval Chain with Status Checks
name: Tiered Verification
on:
workflow_dispatch:
inputs:
environment:
required: true
default: 'staging'
jobs:
staging:
runs-on: ubuntu-latest
steps:
- run: ./deploy-staging.sh
production:
needs: staging
if: ${{ success() && github.event.inputs.environment == 'production' }}
runs-on: ubuntu-latest
steps:
- run: ./deploy-prod.sh
- State-Aware Caching
name: Intelligent Caching
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/cache@v3
id: cache
with:
path: node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
- name: Install Dependencies
if: ${{ steps.cache.outputs.cache-hit != 'true' }}
run: npm ci
- name: Save Cache on Failure
if: ${{ failure() }}
uses: actions/cache/save@v3
with:
path: node_modules
key: ${{ steps.cache.outputs.cache-primary-key }}
Mastering Conditional Logic in GitHub Actions: Practical If-Else Patterns for CI/CD
Branch-Specific Deployment Gates
name: Environment Routing
on: [push]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Prod Deployment
if: ${{ contains(github.ref, 'refs/heads/main') }}
run: ./deploy-prod.sh
- name: Staging Deployment
if: ${{ contains(github.ref, 'refs/heads/staging') }}
run: ./deploy-staging.sh
- name: Dev Deployment
if: ${{ !contains(github.ref, 'main|staging') }}
run: ./deploy-dev.sh
- Matrix Strategy with Conditional Exclusion
name: Smart Matrix Builds
on: [push]
jobs:
test:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node: [18, 20]
exclude:
- os: windows-latest
node: 20
if: ${{ github.ref != 'refs/heads/main' }}
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node }}
- Manual Approval Workflow
name: Production Gate
on:
workflow_dispatch:
inputs:
confirm:
description: 'Type "DEPLOY" to confirm'
required: true
jobs:
deploy-prod:
if: ${{ github.event.inputs.confirm == 'DEPLOY' }}
runs-on: ubuntu-latest
steps:
- run: echo "Deploying to production..."
- run: ./deploy-prod.sh
- Failure-Driven Rollback
name: Auto-Rollback System
on: [workflow_run]
jobs:
rollback:
if: ${{ failure() }}
runs-on: ubuntu-latest
steps:
- name: Restore Backup
run: ./restore-previous-version.sh
- name: Notify Team
run: ./send-alert.sh
- Documentation-Only Skipper
name: Doc Impact Filter
on: [push]
jobs:
check-changes:
runs-on: ubuntu-latest
outputs:
docs-only: ${{ steps.filter.outputs.result }}
steps:
- uses: actions/checkout@v4
- name: Detect Doc Changes
id: filter
run: |
changed_files=$(git diff --name-only HEAD^)
if [[ "$changed_files" =~ ^docs/ ]]; then
echo "result=true" >> $GITHUB_OUTPUT
else
echo "result=false" >> $GITHUB_OUTPUT
fi
build:
needs: check-changes
if: ${{ needs.check-changes.outputs.docs-only == 'false' }}
runs-on: ubuntu-latest
steps:
- run: ./build.sh
- Tag-Based Semantic Release
name: Automated Versioning
on:
push:
tags:
- 'v*'
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Parse Version
id: version
run: |
echo "version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
- name: Publish Package
if: ${{ !contains(steps.version.outputs.version, '-') }}
run: ./publish-stable.sh ${{ steps.version.outputs.version }}
- name: Publish Beta
if: ${{ contains(steps.version.outputs.version, '-beta') }}
run: ./publish-beta.sh ${{ steps.version.outputs.version }}
- Parallel Dependency Chain
name: Parallel Pipeline
on: [push]
jobs:
unit-test:
runs-on: ubuntu-latest
steps:
- run: ./test-unit.sh
integration-test:
runs-on: ubuntu-latest
steps:
- run: ./test-integration.sh
deploy:
needs: [unit-test, integration-test]
if: ${{ always() && (needs.unit-test.result == 'success' || needs.integration-test.result == 'success') }}
runs-on: ubuntu-latest
steps:
- run: ./conditional-deploy.sh
- Environment-Specific Configuration
name: Contextual Config
on: [push]
jobs:
setup:
runs-on: ubuntu-latest
outputs:
env: ${{ steps.detect.outputs.env }}
steps:
- name: Detect Environment
id: detect
run: |
if [[ ${{ github.ref == 'refs/heads/main' }} ]]; then
echo "env=prod" >> $GITHUB_OUTPUT
else
echo "env=dev" >> $GITHUB_OUTPUT
fi
build:
needs: setup
runs-on: ubuntu-latest
env:
DEPLOY_ENV: ${{ needs.setup.outputs.env }}
steps:
- run: ./build.sh --env $DEPLOY_ENV
- A*uto-Cancel Redundant Workflows*
name: Efficient CI
on: [push]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: ./build.sh
- Composite Condition Validation
name: Multi-Factor Check
on:
pull_request:
types: [opened, synchronize]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check Requirements
id: checks
run: |
echo "has_tests=$([ -d "tests" ] && echo "true" || echo "false")" >> $GITHUB_OUTPUT
echo "docs_updated=$([ $(git diff HEAD^ -- docs/ | wc -l) -gt 0 ] && echo "true" || echo "false")" >> $GITHUB_OUTPUT
- name: Approve PR
if: ${{ steps.checks.outputs.has_tests == 'true' && steps.checks.outputs.docs_updated == 'true' }}
run: gh pr review --approve
Top comments (0)