Skip to content
Merged
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
24 changes: 23 additions & 1 deletion .github/workflows/cd-base.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
# ===============================================
# CI/CD Pipeline: Pull GHCR image -> Re-tag -> Push to DockerHub -> Deploy with Terraform
# ===============================================
# Description:
# This workflow takes a Docker image from GHCR (GitHub Container Registry) generated by a PR or push,
# retags it with the DockerHub username, pushes it to DockerHub, and then deploys the latest image
# to Cloud Run using Terraform. It also handles initial database table creation if necessary.
#
# Inputs:
# - deployment_env: Deployment environment (e.g., staging, production)
# - image_uri: URI of the image in GHCR (e.g., ghcr.io/org/repo:tag)
#
# Outputs:
# - dockerhub_image: URI of the retagged image pushed to DockerHub
# ===============================================

on:
workflow_call:
inputs:
Expand All @@ -9,6 +25,9 @@ on:
type: string

jobs:
# -----------------------------------------------
# Job: Pull image from GHCR, retag, and push to DockerHub
# -----------------------------------------------
pull-tag-push:
runs-on: ubuntu-latest
outputs:
Expand Down Expand Up @@ -48,8 +67,11 @@ jobs:

docker push ${DOCKERHUB_IMAGE}

echo "image_uri=${PUBLIC_IMAGE}" >> $GITHUB_OUTPUT
echo "image_uri=${PUBLIC_IMAGE}" >> $GITHUB_OUTPUT # <-- output this way given that github actions will censor secrets

# -----------------------------------------------
# Job: Deploy application to GCP using Terraform
# -----------------------------------------------
deploy:
needs: pull-tag-push
runs-on: ubuntu-latest
Expand Down
13 changes: 12 additions & 1 deletion .github/workflows/cd-stg.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
# CD pipeline for staging environment runs when PR gets merged with main branch
# =====================================================
# CD Pipeline: Staging Environment
# =====================================================
# Description:
# This workflow deploys the latest register-ticket-api image
# to the staging environment whenever a PR is merged into main
# or when triggered manually via workflow_dispatch.
#
# Jobs:
# - deploy-to-stg: Deploys the application using the reusable cd-base workflow
# - promote-to-stg-passed: Tags the image as stg-passed after successful deployment
# =====================================================

name: CD pipeline for staging environment

Expand Down
19 changes: 18 additions & 1 deletion .github/workflows/ci-dev-branches.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,21 @@
# Static Code Analysis, runs when push to feature/**, feat/**, fix/** branches.
# ===============================================
# CI Workflow: Dev Branch Validations
# ===============================================
# Description:
# This workflow runs static code analysis on development branches
# to enforce code quality and style before merging into main.
#
# Triggers:
# - Push to any branch matching feature/**, feat/**, or fix/**
#
# Jobs:
# - static-code-analysis: Delegates to the shared workflow
# ./.github/workflows/static-code-analysis.yml
#
# Inputs:
# - coverage_artifact: Boolean flag to enable/disable coverage artifact
# generation. Here set to false.
# ===============================================

name: Dev branch validations

Expand Down
21 changes: 21 additions & 0 deletions .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
# =====================================================
# CI/CD Workflow: Run Integration Tests
# =====================================================
# Description:
# This workflow executes integration tests for the project.
# It can run in different deployment environments (local, staging, production)
# and conditionally starts/stops local services using Docker Compose.
#
# Triggered via:
# - workflow_call (called from other workflows)
#
# Inputs:
# deployment_env: Deployment environment (e.g., local, staging, prod)
#
# Jobs:
# - run-integration-tests:
# Checks out code, installs dependencies, loads environment variables,
# optionally spins up Docker Compose services for local testing,
# executes integration tests, and cleans up resources.
# =====================================================

name: Run integration tests
on:
workflow_call:
Expand Down
23 changes: 22 additions & 1 deletion .github/workflows/pr-validations.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,25 @@
# Static Code Analysis and test validation workflow. Runs only on pull requests targeting the main branch.
# =====================================================
# CI/CD Workflow: Pull Request Validations
# =====================================================
# Description:
# This workflow runs validations on pull requests targeting the main branch.
# It includes static code analysis, (optionally SonarQube analysis), integration tests,
# and building & pushing Docker images to GitHub Container Registry (GHCR).
#
# Triggered via:
# - pull_request events on the main branch
#
# Jobs:
# - static-code-analysis:
# Runs static code checks and optionally generates coverage artifacts.
#
# - run-integration-tests:
# Executes integration tests in a specified environment. Depends on static code analysis.
#
# - build-and-push-register-ticket-api:
# Builds the Docker image for the register-ticket-api service and pushes it to GHCR.
# Depends on integration tests to ensure only tested code is pushed.
# =====================================================

name: Pull Requests Validations

Expand Down
21 changes: 20 additions & 1 deletion .github/workflows/static-code-analysis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,23 @@
# Static Code Analysis, called when PR to main or push to feature/**, feat/**, fix/** branches.
# =====================================================
# CI Workflow: Static Code Analysis
# =====================================================
# Description:
# This workflow performs static code analysis, lints, and unit tests
# for Python projects. It supports generating coverage reports optionally.
#
# Triggered via:
# - workflow_call: Can be invoked by other workflows
#
# Inputs:
# - coverage_artifact (boolean, required):
# If true, generates coverage reports and uploads them as artifacts.
# If false, runs tests with console-only coverage output.
#
# Jobs:
# - static-code-analysis:
# Runs pre-commit checks, installs dependencies, executes unit tests,
# and optionally uploads coverage reports.
# =====================================================

name: Static Code Analysis
on:
Expand Down
20 changes: 20 additions & 0 deletions .github/workflows/teardown.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
# =====================================================
# CI/CD Workflow: PANIC - Destroy Infrastructure
# =====================================================
# Description:
# This workflow is used to destroy all infrastructure for a given environment.
# It is intended for emergency or complete teardown scenarios.
#
# Triggered via:
# - workflow_dispatch: Manual trigger from GitHub UI
#
# Inputs:
# - deployment_env (choice, required): The target environment to destroy. Options: stg, prd
# - confirmation (string, required): Must be exactly "DESTROY" to confirm execution.
#
# Jobs:
# - destroy-infrastructure:
# Validates the confirmation input, initializes Terraform, selects the
# appropriate workspace, and destroys all resources.
# =====================================================

name: PANIC - destroy infrastructure

on:
Expand Down
38 changes: 37 additions & 1 deletion tests/integration/test_tickets_registration.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""
Integration tests for the ticket registration API and database flow.
"""

from typing import Any

import requests
Expand All @@ -12,7 +16,17 @@ def test_register_ticket_flow(
base_url: str, db_connection: connection, test_username: str = "spuertaf"
) -> None:
"""
Tests whole ticket registration flow works as expected.
Test the full ticket registration flow for a user.

Sends a POST request to register a ticket for the specified user, then
verifies that the ticket is correctly stored in the database with
expected values.

Args:
base_url (str): Base URL of the ticket registration API.
db_connection (connection): Active PostgreSQL database connection.
test_username (str, optional): Username for which the ticket is registered.
Defaults to "spuertaf".
"""
headers: dict[str, str] = {"Content-Type": "application/json"}
payload: dict[str, str] = {"seat": "A12", "gate": "G1"}
Expand Down Expand Up @@ -59,6 +73,17 @@ def test_register_ticket_fails_when_already_registered(
base_url: str,
test_username: str = "juanperez", # different user so tests don't collide
) -> None:
"""
Test that registering the same ticket twice fails.

Sends a POST request to register a ticket for the user, then attempts
to register the same ticket again and expects an error.

Args:
base_url (str): Base URL of the ticket registration API.
test_username (str, optional): Username for which the ticket is registered.
Defaults to "juanperez".
"""
headers: dict[str, str] = {"Content-Type": "application/json"}
payload: dict[str, str] = {
"seat": "B05",
Expand All @@ -78,6 +103,17 @@ def test_register_ticket_fails_when_already_registered(


def test_invalid_ticket_registration_error(base_url: str, test_username: str = "spuertaf") -> None:
"""
Test that registering a ticket with invalid data returns an error.

Sends a POST request with invalid seat/gate values and expects the API
to return an error code.

Args:
base_url (str): Base URL of the ticket registration API.
test_username (str, optional): Username for which the ticket is registered.
Defaults to "spuertaf".
"""
headers: dict[str, str] = {"Content-Type": "application/json"}
payload: dict[str, str] = {"seat": "B05", "gate": "G12"}
endpoint: str = f"/api/users/{test_username}/tickets"
Expand Down
Loading