Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,25 @@ jobs:
source .venv/bin/activate
coverage report --fail-under=70
working-directory: backend

docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7

- name: Build backend image
run: docker build -t kaapi-backend:ci ./backend

- name: Prepare env for compose validation
run: cp .env.test.example .env

- name: Validate compose files
env:
RABBITMQ_USER: ci
RABBITMQ_PASSWORD: ci
RABBITMQ_VHOST: ci
run: |
for f in docker-compose.yml docker-compose.dev.yml docker-compose.staging.yml; do
echo "Validating $f"
docker compose -f "$f" config -q
done
25 changes: 25 additions & 0 deletions .github/workflows/create-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,32 @@ on:
- "v[0-9]+.[0-9]+.[0-9]+" # Deploy only when tags like v1.0.0, v2.1.0, etc., are created

jobs:
verify-ci:
runs-on: ubuntu-latest
permissions:
contents: read
actions: read
steps:
- name: Confirm CI passed on the tagged commit
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
SHA="${{ github.sha }}"
echo "Checking Kaapi CI conclusion for ${SHA}"
CONCLUSION=$(gh api \
"repos/${{ github.repository }}/actions/runs?head_sha=${SHA}" \
--jq 'first(.workflow_runs[]
| select(.name == "Kaapi CI" and .status == "completed")
| .conclusion) // "missing"')
echo "Kaapi CI conclusion: ${CONCLUSION}"
if [ "${CONCLUSION}" != "success" ]; then
echo "::error::Kaapi CI has not passed for ${SHA} (conclusion: ${CONCLUSION}). Aborting release."
exit 1
fi

build:
needs: verify-ci
runs-on: ubuntu-latest
environment: AWS_ENV_VARS

Expand Down
31 changes: 25 additions & 6 deletions .github/workflows/deploy-staging.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
name: Deploy Kaapi staging to EC2

on:
push:
workflow_run:
workflows: ["Kaapi CI"]
branches: [main]
types: [completed]
workflow_dispatch:

concurrency:
Expand All @@ -13,6 +15,10 @@ jobs:
deploy:
runs-on: ubuntu-latest
environment: AWS_STAGING_ENV
# workflow_dispatch runs unconditionally; workflow_run only on a green CI.
if: >-
${{ github.event_name == 'workflow_dispatch' ||
github.event.workflow_run.conclusion == 'success' }}

permissions:
id-token: write
Expand Down Expand Up @@ -42,19 +48,32 @@ jobs:
echo "Sent SSM command: $CMD_ID"

- name: Wait for SSM command to finish
timeout-minutes: 10

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added a timeout of 20 minutes so the workflow has a maximum runtime of 20 minutes, eliminating the need to add a sleep method here.

env:
INSTANCE_ID: ${{ secrets.STAGING_EC2_INSTANCE_ID }}
CMD_ID: ${{ steps.ssm.outputs.cmd_id }}
POLL_INTERVAL: "10"
run: |
WAIT_EXIT=0
aws ssm wait command-executed \
--command-id "$CMD_ID" \
--instance-id "$INSTANCE_ID" || WAIT_EXIT=$?
poll_status() {
aws ssm get-command-invocation \
--command-id "$CMD_ID" \
--instance-id "$INSTANCE_ID" \
--query "Status" \
--output text 2>/dev/null || echo "Pending"
}

STATUS=$(poll_status)
until [[ "$STATUS" =~ ^(Success|Failed|Cancelled|TimedOut)$ ]]; do
echo "Status: $STATUS — waiting ${POLL_INTERVAL}s"
sleep "$POLL_INTERVAL"
STATUS=$(poll_status)
done

echo "Final status: $STATUS"
aws ssm get-command-invocation \
--command-id "$CMD_ID" \
--instance-id "$INSTANCE_ID" \
--query '{Status:Status,Stdout:StandardOutputContent,Stderr:StandardErrorContent}' \
--output json

exit $WAIT_EXIT
[[ "$STATUS" == "Success" ]]
49 changes: 49 additions & 0 deletions .github/workflows/pr-title-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: PR Title Check

on:
pull_request_target:
types: [opened, edited, reopened, synchronize]

permissions:
pull-requests: read

concurrency:
group: pr-title-${{ github.event.pull_request.number }}
cancel-in-progress: true

jobs:
validate:
runs-on: ubuntu-latest
steps:
- name: Validate PR title follows Conventional Commits
env:
PR_TITLE: ${{ github.event.pull_request.title }}
run: |
# type(scope): summary — scope optional, `!` marks a breaking change.
# Keep types in sync with what the PR formatter is allowed to emit.
PATTERN='^(feat|fix|chore|docs|refactor|perf|test|ci|build|style|revert)(\([a-z0-9 _/-]+\))?!?: .+'

echo "Checking PR title: $PR_TITLE"
if echo "$PR_TITLE" | grep -qE "$PATTERN"; then
echo "PR title is valid."
exit 0
fi

echo "::error title=Invalid PR title::'$PR_TITLE' is not in Conventional Commits format"
{
echo "### ❌ PR title is not in Conventional Commits format"
echo ""
echo "**Your title:** \`$PR_TITLE\`"
echo ""
echo "**Required format:** \`type(scope): short summary\` (scope is optional)"
echo ""
echo "**Allowed types:** feat, fix, chore, docs, refactor, perf, test, ci, build, style, revert"
echo ""
echo "**Good examples:**"
echo "- \`feat(collection): Add new fields\`"
echo "- \`fix(auth): Correct token expiry check\`"
echo "- \`chore(ci): Add PR title check workflow\`"
echo ""
echo "Edit the PR title to match and this check re-runs automatically."
} >> "$GITHUB_STEP_SUMMARY"
exit 1
Loading