Search code examples
firebasegoogle-cloud-functionsgithub-actionsgoogle-cloud-rungoogle-cloud-build

Next.js, GitHub Actions CI/CD, Google Cloud Build & Run, Firebase: Issues with Secrets & Environment Variables


I've successfully build and deployed the webapp onto Google Cloud Run. I'm trying to send call a firebase Cloud Function but it requires some keys for the config, I've entered the keys on my repo's Secrets. GitHub Actions does see the keys, but I want to also use the keys in my environment. After doing some research, I'm still stumped. I tried logging the process.env.KEY_ID (example) on my browser and it returns undefined, I'm not sure if this is the intended outcome because then it wouldn't be a secret if it's easily logged through the browser but the Cloud Function url is undefined when it should've been my Firebase Project ID. Any help is very much appreciated. Thank you.

Browser's Console Log

Access to fetch at 'https://us-central1-undefined.cloudfunctions.net/addData' from origin 'my_url_redacted' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

POST https://us-central1-undefined.cloudfunctions.net/addData net::ERR_FAILED

google-cloudrun.yml

# .github/workflows/deploy.yml
name: Build with Cloud Build and Deploy to Cloud Run
on:
  push:
    branches:
      - master
env:
  PROJECT_ID: ${{ secrets.GCP_PROJECT_ID }}
  SERVICE: xxx
  RUN_REGION: xxx
  SA_KEY_JSON: ${{ secrets.GCP_SA_CREDS }}
jobs:
  deploy:
    name: Deploy to Cloud Run
    runs-on: ubuntu-latest
    if: contains(github.event.head_commit.message, 'to deploy')
    steps:
      - uses: actions/checkout@v3

      # Setup gcloud CLI
      # - uses: google-github-actions/setup-gcloud@v0
      #   with:
      #     version: "395.0.0"
      #     service_account_key: ${{ secrets.GCP_SA_CREDS }}
      #     project_id: ${{ secrets.GCP_PROJECT_ID }}

      # Google Auth via Credentials JSON
      - name: Google Auth
        id: auth
        uses: 'google-github-actions/auth@v2'
        with: 
          credentials_json: '${{ secrets.GCP_SA_CREDS }}'

      - name: 'Set up Cloud SDK'
        uses: 'google-github-actions/setup-gcloud@v2'

      - name: 'Use gcloud CLI'
        run: 'gcloud info'

      - name: Set Environment Variables
        run: |
          echo NEXT_PUBLIC_FIREBASE_API_KEY='${{ secrets.NEXT_PUBLIC_FIREBASE_API_KEY }}' > .env.local
          echo NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN='${{ secrets.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN }}' >> .env.local
          echo NEXT_PUBLIC_FIREBASE_DATABASE_URL='${{ secrets.NEXT_PUBLIC_FIREBASE_DATABASE_URL }}' >> .env.local
          echo NEXT_PUBLIC_FIREBASE_PROJECT_ID='${{ secrets.NEXT_PUBLIC_FIREBASE_PROJECT_ID }}' >> .env.local
          echo NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET='${{ secrets.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET }}' >> .env.local
          echo NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID='${{ secrets.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID }}' >> .env.local
          echo NEXT_PUBLIC_FIREBASE_APP_ID='${{ secrets.NEXT_PUBLIC_FIREBASE_APP_ID }}' >> .env.local

      # Build and push image to Google Container Registry
      - name: Build
        run: gcloud builds submit --tag gcr.io/$PROJECT_ID/$SERVICE:$GITHUB_SHA

      - name: Deploy
        run: gcloud run deploy $SERVICE --image gcr.io/$PROJECT_ID/$SERVICE:$GITHUB_SHA --platform managed --region $RUN_REGION --allow-unauthenticated

next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
    typescript: {
        ignoreBuildErrors: true,
    },
    output: "standalone",
    reactStrictMode: true,
    env: {
        NEXT_PUBLIC_FIREBASE_API_KEY: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
        NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
        NEXT_PUBLIC_FIREBASE_DATABASE_URL: process.env.NEXT_PUBLIC_FIREBASE_DATABASE_URL,
        NEXT_PUBLIC_FIREBASE_PROJECT_ID: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
        NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
        NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
        NEXT_PUBLIC_FIREBASE_APP_ID: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
    }
}

module.exports = nextConfig

page.tsx

const firebaseConfig = {
    apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
    authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
    databaseURL: process.env.NEXT_PUBLIC_FIREBASE_DATABASE_URL,
    projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
    storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
    messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
    appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
};

const app = initializeApp(firebaseConfig);
        const addDataFunction = httpsCallable(getFunctions(app), 'addData');
        addDataFunction({ cloudFunctionData }).then((result) => {
            // Read result of the Cloud Function
            const data: any = result.data;
            const sanitizedMessage = data.text;
            console.log('Result: ', data);
        }).catch((error) => {
            const code = error.code;
            const message = error.message;
            const details = error.details;
            console.log('Code: ', code);
            console.log('Message: ', message);
            console.log('Details: ', details);
            console.log('APP ID: ', firebaseConfig.appId);
        })

Solution

  • Turns out, I just had to change .env.local to .env in GA workflow as it is in production.

    Thanks @DevonRay.