diff --git a/.github/workflows/cicd.yaml b/.github/workflows/cicd.yaml new file mode 100644 index 0000000..8e7880f --- /dev/null +++ b/.github/workflows/cicd.yaml @@ -0,0 +1,246 @@ +name: "[PR] Deploy Pipeline" + +on: + push: + branches: + - main + - feature/pipelines # Додано для запуску з гілки feature/pipelines, видалити у фінальній версії + +permissions: + id-token: write # ОБОВ'ЯЗКОВО для OIDC логіну + contents: read + packages: write + +jobs: + deploy_postgres_and_key_vault: + name: Deploy postgres database and key vault + runs-on: ubuntu-latest + environment: dev + env: + PG_SERVER_NAME: ${{ vars.AZURE_POSTGRESQL_SERVER_NAME }} + PG_ADMIN_USER: ${{ secrets.AZURE_POSTGRESQL_ADMIN_USER }} + PG_ADMIN_PASSWORD: ${{ secrets.AZURE_POSTGRESQL_ADMIN_PASSWORD }} + RESOURCE_GROUP: ${{ secrets.AZURE_RESOURCE_GROUP }} + KEY_VAULT_NAME: ${{ vars.KEY_VAULT_NAME }} + steps: + - name: Log in to Azure with OIDC + uses: azure/login@v1 + with: + client-id: ${{ vars.AZURE_CLIENT_ID }} + tenant-id: ${{ vars.AZURE_TENANT_ID }} + subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }} + + - name: Create key vault + run: | + echo "Create Key Vault" + set +e + KEY_VAULT_EXISTS=$(az keyvault show \ + --name $KEY_VAULT_NAME \ + --resource-group $RESOURCE_GROUP \ + --query "name" -o tsv 2>/dev/null) + set -e + + echo "before if" + if [ -z "$KEY_VAULT_EXISTS" ]; then + echo "Key Vault $KEY_VAULT_NAME does NOT exist." + az keyvault create \ + --name $KEY_VAULT_NAME \ + --resource-group $RESOURCE_GROUP \ + --location westeurope \ + --sku standard + else + echo "Key Vault exists: $KEY_VAULT_EXISTS" + fi + + echo "Assign Key Vault Secrets Officer role to the SPN" + az role assignment create \ + --assignee ${{ vars.AZURE_CLIENT_ID }} \ + --role "Key Vault Secrets Officer" \ + --scope "/subscriptions/${{ vars.AZURE_SUBSCRIPTION_ID }}/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.KeyVault/vaults/$KEY_VAULT_NAME" + + echo "Assign Key Vault Secrets Officer role to the dev group" + az role assignment create \ + --assignee ${{ vars.DEV_GROUP_ID }} \ + --role "Key Vault Secrets Officer" \ + --scope "/subscriptions/${{ vars.AZURE_SUBSCRIPTION_ID }}/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.KeyVault/vaults/$KEY_VAULT_NAME" + + - name: Deploy PG Flexible Server + run: | + IP=$(curl -s https://ifconfig.me) + echo "Runner Public IP: $IP" + + echo "Create PostgreSQL Flexible Server" + + set +e + PGDB_EXISTS=$(az postgres flexible-server show \ + --name "$PG_SERVER_NAME" \ + --resource-group "$RESOURCE_GROUP" \ + --query "name" -o tsv 2>/dev/null) + set -e + + if [ -z "$PGDB_EXISTS" ]; then + echo "PostgresSQL PG_SERVER_NAME does NOT exist." + az postgres flexible-server create \ + --resource-group $RESOURCE_GROUP \ + --name $PG_SERVER_NAME \ + --location westeurope \ + --admin-user $PG_ADMIN_USER \ + --admin-password $PG_ADMIN_PASSWORD \ + --tier Burstable \ + --sku-name Standard_B1ms \ + --storage-size 32 \ + --version 16 \ + --public-access $IP + else + echo "PostgresSQL exists: $PGDB_EXISTS" + fi + + echo "Check PostgreSQL server status" + az postgres flexible-server show \ + --name $PG_SERVER_NAME \ + --resource-group $RESOURCE_GROUP + + echo "Create PostgreSQL database" + az postgres flexible-server db create \ + --resource-group "$RESOURCE_GROUP" \ + --server-name "$PG_SERVER_NAME" \ + --database-name tasks_db + + echo "Add PostgreSQL secrets in key vault." + az keyvault secret set \ + --vault-name $KEY_VAULT_NAME \ + --name "pg-admin-user" \ + --value $PG_ADMIN_USER + + az keyvault secret set \ + --vault-name $KEY_VAULT_NAME \ + --name "pg-admin-password" \ + --value $PG_ADMIN_PASSWORD + + build_docker_image: + name: Build docker image and save in Github Container Registry + runs-on: ubuntu-latest + environment: dev + env: + PG_ADMIN_USER: ${{ secrets.AZURE_POSTGRESQL_ADMIN_USER }} + PG_ADMIN_PASSWORD: ${{ secrets.AZURE_POSTGRESQL_ADMIN_PASSWORD }} + RESOURCE_GROUP: ${{ secrets.AZURE_RESOURCE_GROUP }} + KEY_VAULT_NAME: ${{ vars.KEY_VAULT_NAME }} + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Build docker images and push it to GitHub Container Registry + run: | + echo "Log in to GitHub Container Registry" + echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin + + REPO_OWNER_LOWER=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]') + + echo "Build BE docker image" + docker build -t ghcr.io/$REPO_OWNER_LOWER/rest-api-backend:latest backend_app + echo "Docker image built successfully" + + echo "Push BE docker image to GitHub Container Registry" + docker push ghcr.io/$REPO_OWNER_LOWER/rest-api-backend:latest + + echo "Build FE docker image" + docker build -t ghcr.io/$REPO_OWNER_LOWER/rest-api-frontend:latest frontend_app + echo "Docker image built successfully" + + echo "Push FE docker image to GitHub Container Registry" + docker push ghcr.io/$REPO_OWNER_LOWER/rest-api-frontend:latest + + deploy_web_apps: + name: Deploy frontend and backend web apps + runs-on: ubuntu-latest + environment: dev + needs: [deploy_postgres_and_key_vault, build_docker_image] + env: + PG_ADMIN_USER: ${{ secrets.AZURE_POSTGRESQL_ADMIN_USER }} + PG_ADMIN_PASSWORD: ${{ secrets.AZURE_POSTGRESQL_ADMIN_PASSWORD }} + RESOURCE_GROUP: ${{ secrets.AZURE_RESOURCE_GROUP }} + KEY_VAULT_NAME: ${{ vars.KEY_VAULT_NAME }} + steps: + - name: Log in to Azure with OIDC + uses: azure/login@v1 + with: + client-id: ${{ vars.AZURE_CLIENT_ID }} + tenant-id: ${{ vars.AZURE_TENANT_ID }} + subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }} + + - name: Deploy frontend and backend web apps + run: | + echo "Check if App Service Plan exists" + set +e + PLAN_EXISTS=$(az appservice plan show \ + --resource-group $RESOURCE_GROUP \ + --name rest-api-plan \ + --query "name" -o tsv 2>/dev/null) + set -e + + if [ -z "$PLAN_EXISTS" ]; then + echo "Create App Service Plan" + az appservice plan create \ + --resource-group $RESOURCE_GROUP \ + --name rest-api-plan \ + --sku B1 \ + --is-linux \ + --location westeurope + else + echo "App Service Plan exists: $PLAN_EXISTS" + fi + + BACKEND_WEBAPP_NAME="rest-api-${{ vars.WEBAPP_BACKEND_NAME }}" + PG_SERVER_NAME="${{ vars.AZURE_POSTGRESQL_SERVER_NAME }}.postgres.database.azure.com" + REPO_OWNER_LOWER=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]') + + echo "Deploy backend web app" + az webapp create \ + --resource-group $RESOURCE_GROUP \ + --name $BACKEND_WEBAPP_NAME \ + --plan rest-api-plan \ + --container-registry-url ghcr.io \ + --container-image-name $REPO_OWNER_LOWER/rest-api-backend:latest + + echo "Set environment variables for backend web app" + az webapp config appsettings set \ + --resource-group $RESOURCE_GROUP \ + --name $BACKEND_WEBAPP_NAME \ + --settings \ + POSTGRES_HOST=$PG_SERVER_NAME \ + POSTGRES_USER=$PG_ADMIN_USER \ + POSTGRES_PASSWORD=$PG_ADMIN_PASSWORD + + echo "Enable logging for backend web app" + az webapp log config \ + --resource-group $RESOURCE_GROUP \ + --name $BACKEND_WEBAPP_NAME \ + --docker-container-logging filesystem + echo "Enable logging for backend web app" + az webapp log config \ + --resource-group $RESOURCE_GROUP \ + --name $BACKEND_WEBAPP_NAME \ + --docker-container-logging filesystem + + FRONTEND_WEBAPP_NAME="rest-api-${{ vars.WEBAPP_FRONTEND_NAME }}" + + echo "Deploy frontend web app" + az webapp create \ + --resource-group $RESOURCE_GROUP \ + --name $FRONTEND_WEBAPP_NAME \ + --plan rest-api-plan \ + --container-registry-url ghcr.io \ + --container-image-name $REPO_OWNER_LOWER/rest-api-frontend:latest + + echo "Set environment variables for frontend web app" + az webapp config appsettings set \ + --resource-group $RESOURCE_GROUP \ + --name $FRONTEND_WEBAPP_NAME \ + --settings KEY_VAULT_NAME=$KEY_VAULT_NAME + + echo "Enable logging for frontend web app" + az webapp log config \ + --resource-group $RESOURCE_GROUP \ + --name $FRONTEND_WEBAPP_NAME \ + --docker-container-logging filesystem \ No newline at end of file diff --git a/.github/workflows/pgdb-create.yaml b/.github/workflows/pgdb-create.yaml deleted file mode 100644 index c59159c..0000000 --- a/.github/workflows/pgdb-create.yaml +++ /dev/null @@ -1,52 +0,0 @@ -name: "[PR] Create Azure PostgreSQL Server Pipeline" - -on: - push: - branches: - - main - - feature/pipelines # Додано для запуску з гілки feature/pipelines, видалити у фінальній версії - -permissions: - id-token: write # ОБОВ'ЯЗКОВО для OIDC логіну - contents: read - -jobs: - create_pgdb: - name: Creating PostgreSQL Server - runs-on: ubuntu-latest - environment: dev - env: - PG_ADMIN_USER: ${{ secrets.PG_ADMIN_USER }} - PG_ADMIN_PASSWORD: ${{ secrets.PG_ADMIN_PASSWORD }} - RESOURCE_GROUP: ${{ secrets.AZURE_RESOURCE_GROUP }} - steps: - - name: Log in to Azure with OIDC - uses: azure/login@v1 - with: - client-id: ${{ vars.AZURE_CLIENT_ID }} - tenant-id: ${{ vars.AZURE_TENANT_ID }} - subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }} - - - name: Deploy PG Flexible Server - run: | - IP=$(curl -s https://ifconfig.me) - echo "Runner Public IP: $IP" - - echo "Create PostgreSQL Flexible Server" - PGDB_NAME="pg-rest-api-westeurope" - az postgres flexible-server create \ - --resource-group $RESOURCE_GROUP \ - --name $PGDB_NAME \ - --location westeurope \ - --admin-user $PG_ADMIN_USER \ - --admin-password $PG_ADMIN_PASSWORD \ - --tier Burstable \ - --sku-name Standard_B1ms \ - --storage-size 32 \ - --version 16 \ - --public-access $IP - - echo "Check PostgreSQL server status" - az postgres flexible-server show \ - --name $PGDB_NAME \ - --resource-group $RESOURCE_GROUP \ No newline at end of file diff --git a/.github/workflows/rg-cleanup.yaml b/.github/workflows/rg-cleanup.yaml index ae22539..a57a543 100644 --- a/.github/workflows/rg-cleanup.yaml +++ b/.github/workflows/rg-cleanup.yaml @@ -15,8 +15,6 @@ jobs: runs-on: ubuntu-latest environment: dev env: - PG_ADMIN_USER: ${{ secrets.PG_ADMIN_USER }} - PG_ADMIN_PASSWORD: ${{ secrets.PG_ADMIN_PASSWORD }} RESOURCE_GROUP: ${{ secrets.AZURE_RESOURCE_GROUP }} steps: - name: Log in to Azure with OIDC @@ -27,6 +25,4 @@ jobs: subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }} - name: Delete all resources in the resource group - run: | - echo "Generate Random PostgreSQL Server Name" - az resource list --resource-group $RESOURCE_GROUP --query "[].id" -o tsv | xargs -I {} az resource delete --ids {} \ No newline at end of file + run: az resource list --resource-group $RESOURCE_GROUP --query "[].id" -o tsv | xargs -I {} az resource delete --ids {} \ No newline at end of file diff --git a/frontend_app/src/components/index.tsx b/frontend_app/src/components/index.tsx index 5371697..a62cf34 100644 --- a/frontend_app/src/components/index.tsx +++ b/frontend_app/src/components/index.tsx @@ -1,3 +1,19 @@ import TaskManager from './TaskManager'; export { TaskManager }; + + +const optimize = ( + fn: (input: any) => any, +): any => { + const cache = {}; + + return (input) => { + if (cache[input]) { + return cache[input]; + } + const result = fn(input); + cache[input] = result; + return result; + } +}