<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Izehiuwa Igiebor Omogiate </title>
    <description>The latest articles on DEV Community by Izehiuwa Igiebor Omogiate  (@josueize).</description>
    <link>https://dev.to/josueize</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3954707%2F246623c3-e0f4-417e-8bd2-e70f46942929.jpeg</url>
      <title>DEV Community: Izehiuwa Igiebor Omogiate </title>
      <link>https://dev.to/josueize</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/josueize"/>
    <language>en</language>
    <item>
      <title>How I Set Up a Full CI/CD Pipeline with Docker, GitHub Actions, and Google Cloud Run</title>
      <dc:creator>Izehiuwa Igiebor Omogiate </dc:creator>
      <pubDate>Sun, 31 May 2026 18:37:27 +0000</pubDate>
      <link>https://dev.to/josueize/how-i-set-up-a-full-cicd-pipeline-with-docker-github-actions-and-google-cloud-run-3o72</link>
      <guid>https://dev.to/josueize/how-i-set-up-a-full-cicd-pipeline-with-docker-github-actions-and-google-cloud-run-3o72</guid>
      <description>&lt;p&gt;When I built ScriptForge — a multi-agent AI content automation platform — I wanted every push to main to automatically lint, build, containerize, and deploy without me touching a single command manually.&lt;br&gt;
This is exactly how I did it.&lt;/p&gt;

&lt;p&gt;What We're Building&lt;br&gt;
A 4-stage GitHub Actions pipeline that:&lt;/p&gt;

&lt;p&gt;Checks frontend code — build + type check&lt;br&gt;
Checks backend code — lint + type check&lt;br&gt;
Builds and pushes a Docker image to Google Artifact Registry&lt;br&gt;
Deploys automatically to Google Cloud Run&lt;/p&gt;

&lt;p&gt;Every time you push to main, all 4 stages run in sequence. If any stage fails, the deploy stops. If all pass, your new version is live within minutes — zero manual steps.&lt;/p&gt;

&lt;p&gt;The Stack&lt;/p&gt;

&lt;p&gt;Frontend: React + TypeScript (Vite)&lt;br&gt;
Backend: Python + FastAPI&lt;br&gt;
Containerization: Docker&lt;br&gt;
CI/CD: GitHub Actions&lt;br&gt;
Registry: Google Artifact Registry&lt;br&gt;
Hosting: Google Cloud Run&lt;/p&gt;

&lt;p&gt;Step 1 — Dockerize Your Backend&lt;br&gt;
First, your FastAPI backend needs a Dockerfile:&lt;br&gt;
dockerfileFROM python:3.11-slim&lt;/p&gt;

&lt;p&gt;WORKDIR /app&lt;/p&gt;

&lt;p&gt;COPY requirements.txt .&lt;br&gt;
RUN pip install --no-cache-dir -r requirements.txt&lt;/p&gt;

&lt;p&gt;COPY . .&lt;/p&gt;

&lt;p&gt;EXPOSE 8080&lt;/p&gt;

&lt;p&gt;CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]&lt;/p&gt;

&lt;p&gt;A few things worth noting:&lt;/p&gt;

&lt;p&gt;Cloud Run expects your container to listen on port 8080&lt;br&gt;
Use python:3.11-slim to keep the image small and fast to build&lt;br&gt;
Always copy requirements.txt before your source code — Docker caches layers, so dependencies only reinstall when requirements.txt changes&lt;/p&gt;

&lt;p&gt;Step 2 — Set Up Google Cloud&lt;br&gt;
You need three things configured in GCP before GitHub Actions can deploy:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Enable the required APIs
bashgcloud services enable run.googleapis.com
gcloud services enable artifactregistry.googleapis.com&lt;/li&gt;
&lt;li&gt;Create an Artifact Registry repository
bashgcloud artifacts repositories create your-repo-name \
--repository-format=docker \
--location=us-central1&lt;/li&gt;
&lt;li&gt;Create a Service Account for GitHub Actions
bashgcloud iam service-accounts create github-actions-deployer \
--display-name="GitHub Actions Deployer"
Grant it the minimum permissions needed:
bash# Push images to Artifact Registry
gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \
--member="serviceAccount:&lt;a href="mailto:github-actions-deployer@YOUR_PROJECT_ID.iam.gserviceaccount.com"&gt;github-actions-deployer@YOUR_PROJECT_ID.iam.gserviceaccount.com&lt;/a&gt;" \
--role="roles/artifactregistry.writer"&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Deploy to Cloud Run
&lt;/h1&gt;

&lt;p&gt;gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \&lt;br&gt;
  --member="serviceAccount:&lt;a href="mailto:github-actions-deployer@YOUR_PROJECT_ID.iam.gserviceaccount.com"&gt;github-actions-deployer@YOUR_PROJECT_ID.iam.gserviceaccount.com&lt;/a&gt;" \&lt;br&gt;
  --role="roles/run.admin"&lt;/p&gt;

&lt;h1&gt;
  
  
  Act as the Cloud Run service account
&lt;/h1&gt;

&lt;p&gt;gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \&lt;br&gt;
  --member="serviceAccount:&lt;a href="mailto:github-actions-deployer@YOUR_PROJECT_ID.iam.gserviceaccount.com"&gt;github-actions-deployer@YOUR_PROJECT_ID.iam.gserviceaccount.com&lt;/a&gt;" \&lt;br&gt;
  --role="roles/iam.serviceAccountUser"&lt;br&gt;
Then export the key and save it as a GitHub secret:&lt;br&gt;
bashgcloud iam service-accounts keys create key.json \&lt;br&gt;
  --iam-account=&lt;a href="mailto:github-actions-deployer@YOUR_PROJECT_ID.iam.gserviceaccount.com"&gt;github-actions-deployer@YOUR_PROJECT_ID.iam.gserviceaccount.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 3 — Add GitHub Secrets&lt;br&gt;
In your GitHub repo go to Settings → Secrets and variables → Actions and add:&lt;br&gt;
SecretValueGCP_SA_KEYContents of key.jsonGCP_PROJECT_IDYour Google Cloud project ID&lt;br&gt;
Never commit key.json to your repo. Add it to .gitignore immediately after creating it.&lt;/p&gt;

&lt;p&gt;Step 4 — The GitHub Actions Workflow&lt;br&gt;
Create .github/workflows/ci.yml:&lt;br&gt;
yamlname: CI&lt;/p&gt;

&lt;p&gt;on:&lt;br&gt;
  push:&lt;br&gt;
    branches: [main]&lt;br&gt;
  pull_request:&lt;br&gt;
    branches: [main]&lt;/p&gt;

&lt;p&gt;jobs:&lt;br&gt;
  frontend-check:&lt;br&gt;
    name: Frontend build &amp;amp; type check&lt;br&gt;
    runs-on: ubuntu-latest&lt;br&gt;
    steps:&lt;br&gt;
      - uses: actions/checkout@v4&lt;br&gt;
      - uses: actions/setup-node@v4&lt;br&gt;
        with:&lt;br&gt;
          node-version: '20'&lt;br&gt;
          cache: 'npm'&lt;br&gt;
          cache-dependency-path: frontend/package-lock.json&lt;br&gt;
      - name: Install dependencies&lt;br&gt;
        run: npm ci&lt;br&gt;
        working-directory: frontend&lt;br&gt;
      - name: Type check&lt;br&gt;
        run: npx tsc --noEmit&lt;br&gt;
        working-directory: frontend&lt;br&gt;
      - name: Build&lt;br&gt;
        run: npm run build&lt;br&gt;
        working-directory: frontend&lt;/p&gt;

&lt;p&gt;backend-check:&lt;br&gt;
    name: Backend lint &amp;amp; type check&lt;br&gt;
    runs-on: ubuntu-latest&lt;br&gt;
    steps:&lt;br&gt;
      - uses: actions/checkout@v4&lt;br&gt;
      - uses: actions/setup-python@v5&lt;br&gt;
        with:&lt;br&gt;
          python-version: '3.11'&lt;br&gt;
      - name: Install dependencies&lt;br&gt;
        run: pip install -r requirements.txt&lt;br&gt;
        working-directory: backend&lt;br&gt;
      - name: Lint with ruff&lt;br&gt;
        run: pip install ruff &amp;amp;&amp;amp; ruff check .&lt;br&gt;
        working-directory: backend&lt;/p&gt;

&lt;p&gt;docker-build-push:&lt;br&gt;
    name: Docker build &amp;amp; push&lt;br&gt;
    runs-on: ubuntu-latest&lt;br&gt;
    needs: [frontend-check, backend-check]&lt;br&gt;
    if: github.ref == 'refs/heads/main'&lt;br&gt;
    steps:&lt;br&gt;
      - uses: actions/checkout@v4&lt;br&gt;
      - name: Authenticate to Google Cloud&lt;br&gt;
        uses: google-github-actions/auth@v2&lt;br&gt;
        with:&lt;br&gt;
          credentials_json: ${{ secrets.GCP_SA_KEY }}&lt;br&gt;
      - name: Configure Docker for Artifact Registry&lt;br&gt;
        run: gcloud auth configure-docker us-central1-docker.pkg.dev&lt;br&gt;
      - name: Build and push Docker image&lt;br&gt;
        run: |&lt;br&gt;
          docker build -t us-central1-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/your-repo-name/backend:${{ github.sha }} ./backend&lt;br&gt;
          docker push us-central1-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/your-repo-name/backend:${{ github.sha }}&lt;/p&gt;

&lt;p&gt;deploy:&lt;br&gt;
    name: Deploy to Google Cloud Run&lt;br&gt;
    runs-on: ubuntu-latest&lt;br&gt;
    needs: docker-build-push&lt;br&gt;
    if: github.ref == 'refs/heads/main'&lt;br&gt;
    steps:&lt;br&gt;
      - uses: actions/checkout@v4&lt;br&gt;
      - name: Authenticate to Google Cloud&lt;br&gt;
        uses: google-github-actions/auth@v2&lt;br&gt;
        with:&lt;br&gt;
          credentials_json: ${{ secrets.GCP_SA_KEY }}&lt;br&gt;
      - name: Deploy to Cloud Run&lt;br&gt;
        uses: google-github-actions/deploy-cloudrun@v2&lt;br&gt;
        with:&lt;br&gt;
          service: your-service-name&lt;br&gt;
          region: us-central1&lt;br&gt;
          image: us-central1-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/your-repo-name/backend:${{ github.sha }}&lt;/p&gt;

&lt;p&gt;How the Pipeline Works&lt;br&gt;
Push to main&lt;br&gt;
     │&lt;br&gt;
     ▼&lt;br&gt;
┌─────────────────┐     ┌─────────────────┐&lt;br&gt;
│ Frontend check  │     │  Backend check  │&lt;br&gt;
│ build + tsc     │     │  lint + types   │&lt;br&gt;
└────────┬────────┘     └────────┬────────┘&lt;br&gt;
         │                       │&lt;br&gt;
         └──────────┬────────────┘&lt;br&gt;
                    │ both pass&lt;br&gt;
                    ▼&lt;br&gt;
         ┌─────────────────────┐&lt;br&gt;
         │  Docker build+push  │&lt;br&gt;
         │  → Artifact Registry│&lt;br&gt;
         └──────────┬──────────┘&lt;br&gt;
                    │&lt;br&gt;
                    ▼&lt;br&gt;
         ┌─────────────────────┐&lt;br&gt;
         │  Deploy to          │&lt;br&gt;
         │  Google Cloud Run   │&lt;br&gt;
         └─────────────────────┘&lt;br&gt;
                    │&lt;br&gt;
                    ▼&lt;br&gt;
              🚀 Live in ~2min&lt;br&gt;
The needs keyword is key here — Docker build only runs if both checks pass. Deploy only runs if Docker push succeeds. One failure stops the whole chain.&lt;/p&gt;

&lt;p&gt;What This Gives You&lt;br&gt;
Before this pipeline, deploying looked like this:&lt;/p&gt;

&lt;p&gt;Build the Docker image locally&lt;br&gt;
Tag it&lt;br&gt;
Authenticate to GCP&lt;br&gt;
Push the image&lt;br&gt;
Open Cloud Console&lt;br&gt;
Trigger a new revision&lt;br&gt;
Wait and check logs manually&lt;/p&gt;

&lt;p&gt;After this pipeline, deploying looks like this:&lt;/p&gt;

&lt;p&gt;git push origin main&lt;/p&gt;

&lt;p&gt;That's it. The pipeline handles everything else. Every commit is tested before it ships. Every deploy is traceable to a specific commit SHA. You never push broken code to production again.&lt;/p&gt;

&lt;p&gt;One Thing I'd Do Differently&lt;br&gt;
I'd add environment-specific secrets earlier. Managing staging vs production Cloud Run services from the start — deploying main to staging automatically and requiring a manual approval for production — is worth setting up before your app has real users, not after.&lt;/p&gt;

&lt;p&gt;Wrapping Up&lt;br&gt;
This exact pipeline runs on ScriptForge in production today. Four jobs, fully automated, zero manual deployment steps. If you're still deploying by hand, this setup takes an afternoon to configure and saves you that time on every single deploy going forward.&lt;br&gt;
The full ScriptForge repo is on GitHub if you want to see the complete workflow file in context.&lt;/p&gt;

&lt;p&gt;Built by Izehiuwa Igiebor Omogiate — Full Stack Developer based in São Paulo, Brazil.&lt;br&gt;
GitHub · LinkedIn · Portfolio&lt;/p&gt;

</description>
      <category>githubactions</category>
      <category>docker</category>
      <category>googlecloud</category>
      <category>cicd</category>
    </item>
    <item>
      <title>Building a Scalable Full Stack App with React and FastAPI</title>
      <dc:creator>Izehiuwa Igiebor Omogiate </dc:creator>
      <pubDate>Wed, 27 May 2026 17:51:03 +0000</pubDate>
      <link>https://dev.to/josueize/building-a-scalable-full-stack-app-with-react-and-fastapi-31b3</link>
      <guid>https://dev.to/josueize/building-a-scalable-full-stack-app-with-react-and-fastapi-31b3</guid>
      <description>&lt;p&gt;How I Built a Modern Full Stack Web Application with React, FastAPI, and PostgreSQL As a full stack web developer, one of the most valuable skills I’ve learned is how to build scalable applications that combine a responsive frontend, a reliable backend, and a well-structured database. Recently, I worked on building a modern web application using React, FastAPI, and PostgreSQL. &lt;/p&gt;

&lt;p&gt;In this article, I want to share the architecture, tools, and lessons I learned during the process.  Why I Chose This Stack I selected this stack because it offers excellent performance, scalability, and developer experience. Frontend: React + TypeScript React made it easy to build reusable UI components and manage the application structure efficiently. Using TypeScript improved code quality and reduced bugs during development. Key benefits: - Reusable components - Faster UI updates - Better maintainability - Strong typing with TypeScript Backend: FastAPI For the backend, I used FastAPI because of its speed and clean developer experience. &lt;/p&gt;

&lt;p&gt;FastAPI provides: - High performance - Automatic API documentation - Easy async support - Strong validation using Pydantic Creating REST APIs with FastAPI was significantly faster compared to traditional backend frameworks. Database: PostgreSQL PostgreSQL handled all application data storage. I used it for: - User authentication data - Application records - API-driven queries - Relational data management PostgreSQL is reliable, scalable, and works extremely well with modern backend systems.  Authentication and Security For authentication, I implemented: - JWT authentication - Password hashing - Protected API routes - Role-based access control Security is one of the most important parts of modern application development, especially when handling user data. State Management with Redux On the frontend, Redux helped manage: - Authentication state - Global application data - API response caching - UI synchronization This improved the consistency and scalability of the application. Deployment with Docker and Kubernetes To improve deployment and scalability, I containerized the application using Docker and explored Kubernetes for orchestration. Benefits included: - Consistent environments - Easier deployment - Better scalability - Improved production management Learning containerization changed the way I think about software deployment. &lt;/p&gt;

&lt;p&gt;Lessons I Learned Building this project taught me several important lessons: - Clean architecture matters - API design is critical - Performance optimization should start early - Debugging skills improve with experience - Documentation saves development time Final Thoughts Modern full stack development is more than just writing frontend and backend code. It involves architecture, deployment, scalability, performance, and user experience. As I continue building projects, I’m focusing on: - AI-integrated applications - scalable cloud systems - production-ready deployments - better developer tooling If you're learning full stack development, my advice is simple: Build real projects consistently and focus on solving real problems. Thanks for reading.&lt;/p&gt;

&lt;p&gt;My git: &lt;a href="https://github.com/Josueize" rel="noopener noreferrer"&gt;https://github.com/Josueize&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>fastapi</category>
      <category>typescript</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
