Objective
A repository at /home/interview/deploy-repo contains a values.yaml file tracking the current Docker image tag and a deploy.sh script that simulates production deployment. When deployments fail, the team must manually revert the configuration.
Task
Complete the workflow at .github/workflows/deploy.yml that triggers on push to main. The deploy job should check out code and run ./deploy.sh. A rollback job should depend on the deploy job, run only when the deployment fails (using if: failure()), check out the code with fetch-depth: 0, restore values.yaml from the previous commit using git checkout HEAD~1 -- values.yaml, and commit the restored file as "CI Bot".
File Path
- Workflow:
/home/interview/deploy-repo/.github/workflows/deploy.yml
- Deployment script:
/home/interview/deploy-repo/deploy.sh
- Config:
/home/interview/deploy-repo/values.yaml
name: Deploy with Automatic Rollback
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run deployment
run: |
chmod +x deploy.sh
./deploy.sh
rollback:
runs-on: ubuntu-latest
needs: deploy
if: failure()
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Restore previous values.yaml
run: |
echo "Deployment failed, initiating rollback..."
git checkout HEAD~1 -- values.yaml
echo "Restored values.yaml to previous version:"
cat values.yaml
- name: Commit rollback
run: |
git config user.name "CI Bot"
git config user.email "[email protected]"
git add values.yaml
git commit -m "Rollback: restore values.yaml after failed deployment"
git push
Explanation
Step 1: Deploy Job
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run deployment
run: |
chmod +x deploy.sh
./deploy.sh
The deploy job checks out the code, makes deploy.sh executable with chmod +x (which adds execute permission), and runs it. If the deployment succeeds, the workflow is done. If it fails (the script exits with a non-zero code), the rollback job kicks in.
Step 2: Rollback Job with if: failure()
rollback:
runs-on: ubuntu-latest
needs: deploy
if: failure()
needs: deploy means the rollback job waits for the deploy job to finish. if: failure() is the key: this job only runs when the deploy job has failed. On a successful deployment, the rollback job is skipped entirely.
Step 3: Restore and Commit
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Restore previous values.yaml
run: git checkout HEAD~1 -- values.yaml
- name: Commit rollback
run: |
git config user.name "CI Bot"
git config user.email "[email protected]"
git add values.yaml
git commit -m "Rollback: restore values.yaml after failed deployment"
git push
fetch-depth: 0 fetches the full git history (by default, checkout only fetches the latest commit). We need the history so git checkout HEAD~1 -- values.yaml can access the previous commit. HEAD~1 means "one commit before the current one." The -- separates the revision from the file path, telling git to restore just that one file from the previous commit. Then we commit the restored file as "CI Bot" and push it.