I want to deploy my create-react-app project to GitHub Pages. But I have a few secret keys. How can I manage these keys inside my React app?
Edited June 2020
Reference #alicia-jasmine
"React is purely a front-end framework. Everything accessible to React (even if you embed it through a build step) will later be visible in the front-end code and someone relatively basic to find. To really keep them secret you MUST have something server side!"
The following answer will actually expose the key in the gh-page branch on GitHub, also the keys will be accessible through the network tab in the developer console.
Original Answer
I'm also using create-react-app, and I found that this can be done by customizing your CI script with GitHub secret settings. (After the setting, you can use environment variables like this in your project.)
const apiKey = process.env.REACT_APP_APIKey
const apiSecret = process.env.REACT_APP_APISecret
To add a secret to your repository, go to your repository's Setting > Secrets, click on Add a new secret. In the screenshot below, I added 2 env variables: REACT_APP_APIKey and REACT_APP_APISecret.
Notice: All the environment variable you want to access with create-react-app need to be prefixed with REACT_APP.
After you have your secret ready, you can take a look at this post, it's about how to add your own Action upon push.
To setup your action script, go to your repository > Actions, an click on Setup workflow your self, and paste in the script provided in the post or take a look at mine script below.
I use the following script to access the 2 environment variables I set on GitHub secret. (You can access the secret you set in the script by ${{ secrets.REACT_APP_APIKey }}.)
name: CI
on:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout#v1
- name: Build
run: |
npm install
npm run-script build
env:
REACT_APP_APIKey: ${{ secrets.REACT_APP_APIKey }}
REACT_APP_APISecret: ${{ secrets.REACT_APP_APISecret }}
- name: Deploy
uses: JamesIves/github-pages-deploy-action#releases/v3
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH: gh-pages
FOLDER: build
After you setup the script, the action will be triggered by any push to master
branch. After you push any commits, you can take a look at the deployment status at actions status.
You can see how hard it is for me to figure it out... so many fail attempts lol. Anyway, hope this will help :)
name: Deploy to GitHub Pages
on:
push:
branches:
- master
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout#v1
- name: Build
run: |
npm install
npm run-script build
env:
REACT_APP_INSTAGRAM_ACCESS_TOKEN: ${{ secrets.REACT_APP_INSTAGRAM_ACCESS_TOKEN }}
REACT_APP_SMTP_SECURE_TOKEN: ${{ secrets.REACT_APP_SMTP_SECURE_TOKEN }}
- name: Deploy
uses: JamesIves/github-pages-deploy-action#releases/v3
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN_KEY }}
BRANCH: gh-pages
FOLDER: dist
You can use like this to add your environment variables from GitHub secrets. This solved my problem.
I support this answer (above)
But I advice to update the gh-pages YML to version 4
Also take a look at environment variables solution because i spent hours to find out the solution
- name: Deploy
uses: JamesIves/github-pages-deploy-action#4.0.0
with:
branch: gh-pages
folder: front-app/dist
To use environment variables, the general approach which is followed is to:
Not expose them to the public
Keep it local at the time of development/production and ignore in .gitignore file.
Make the
static build out of your application Then deploy it to either github
pages or any other static website host.
While working with create-react-app you have their benefits, you can create .env in your root folder.
The structure for the .env file should follow below key-value structure:-
REACT_APP_SECRET_CODE1=dev123
REACT_APP_SECRET_CODE2=prod456
Keys in the file should be prefixed with REACT_APP and you can use these keys to access the variable in your application. For eg. process.env.REACT_APP_SECRET_CODE, this will have the value dev123
If they are truly secret, and so should not be in a repository, then there isn't a way to manage that with github-pages.
If you are okay with having them in a repository, then put them in .env and access via process.env
You can deploy your project on Heroku where you can set up your secret key.
Related
I want to use preview channels on Firebase in order to share and test feature before they go live. Creating the preview channels has been simple but currently I am getting an error when using the preview channel url:
I currently use a .env file that store React environment variables that allow me to connect to firebase but when building and deploying for the preview channels these env variables can't seem to be accessed.
Any ideas on how I can get this to work please
The error is indeed due to your hosted app not having access to those environment variables specifying the Firebase project your app is supposed to connect to (e.g. to authenticate users, manage data etc.). Why they aren't accessible to your GitHub Actions' pipeline steps, I cannot tell without any insights into your setup of course.
However, one approach towards tackling the issue (without having to check your Firebase project configuration in into the version-controlled code) is to store all the required (environment) variables in GitHub so that they become available to the GitHub Actions associated with the GitHub repo you are working on. You can add them at https://github.com/<your-username>/<your-GitHub-repo-name>/settings/variables/actions. Assuming you had a React app, then shipping the environment variables alongside the code to be deployed on a preview channel can be achieved via a firebase-hosting-pull-request.yml script possibly looking similar to this one:
name: Deploy to Firebase Hosting on PR
'on': pull_request
jobs:
build_and_preview:
if: '${{ github.event.pull_request.head.repo.full_name == github.repository }}'
runs-on: ubuntu-latest
env:
REACT_APP_FIREBASE_API_KEY: ${{ vars.REACT_APP_FIREBASE_API_KEY }}
REACT_APP_FIREBASE_AUTH_DOMAIN: ${{ vars.REACT_APP_FIREBASE_AUTH_DOMAIN }}
REACT_APP_FIREBASE_PROJECT_ID: ${{ vars.REACT_APP_FIREBASE_PROJECT_ID }}
REACT_APP_FIREBASE_STORAGE_BUCKET: ${{ vars.REACT_APP_FIREBASE_STORAGE_BUCKET }}
REACT_APP_FIREBASE_MESSAGING_SENDER_ID: ${{ vars.REACT_APP_FIREBASE_MESSAGING_SENDER_ID }}
REACT_APP_FIREBASE_APP_ID: ${{ vars.REACT_APP_FIREBASE_APP_ID }}
steps:
- uses: actions/checkout#v2
- run: npm ci && npm run build
- uses: FirebaseExtended/action-hosting-deploy#v0
with:
repoToken: '${{ secrets.GITHUB_TOKEN }}'
firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_XXX }}'
projectId: XXXXX
expires: 2d
This reads the variables stored for the repo's GitHub Actions and makes them available to all your pipeline steps being executed within the build_and_preview job.
Note: The level at which you define the environment variables inside the yaml-file has an impact on the scope of which parts of pipeline defined in the yaml-file may or may not access them. More on that in the documentation.
If you had more sensitive data to store, you could possibly store those in GitHub secrets (at https://github.com/<your-username>/<your-GitHub-repo-name>/settings/secrets/actions) available to your GitHub Actions as well and then make them available to your deployed code in a similar fashion as we did with variables.
I am trying to set up a GitHub action to automatically deploy to Google App Engine when I push to the master branch. However, I am quite new in the pipelines. I tried to do my homework and I ended up stuck with this.
First, this is my .github/workflows/main.yml:
name: Deployment
on:
push:
branches:
- master
jobs:
deploy:
name: Deploy to App Engine
runs-on: ubuntu-latest
steps:
- name: Google App Engine
uses: google-github-actions/deploy-appengine#v0.4.0
with:
project_id: my-gae-project-id
version: master
credentials: ${{secrets.GOOGLE_APP_ENGINE_KEY}}
flags: --no-cache
deliverables: app.yaml
Now I tried to create the app.yaml in the root directory and also in the .github/workflows directory. None of them works. For now, my app.yaml is just:
runtime: php74
env: standard
Here is the outcome of my GH action everytime:
I tried to do some research and found recommendation to put the app.yaml in a folder, so I also tried .github/workflows/gae/app.yaml and then set it as deliverables: gae/app.yaml - no success. Also tried to put the path in quotes like deliverables: "gae/app.yaml" - no success. Also tried to put the app.yaml to the root and set it as deliverables: ../../app.yaml. In some cases, the app.yaml creates a new GitHub action which is even more irritating.
Now I'm just getting frustrated, because I know this is going to be something silly, but I didn't find many resources about this specific case.
There is a missing step in your main.yml that's why your workflow can't find and access the files. To fix it, add checkout#v2 action in your steps:
name: Deployment
on:
push:
branches:
- master
jobs:
deploy:
name: Deploy to App Engine
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout#v2
- name: Google App Engine
uses: google-github-actions/deploy-appengine#v0.4.0
with:
project_id: my-gae-project-id
version: master
credentials: ${{secrets.GOOGLE_APP_ENGINE_KEY}}
flags: --no-cache
deliverables: app.yaml
You can also visit this official github example for your reference.
I have successfully started my nodejs app (discord bot) in Google App engine and Google Compute Engine but i couldn't auto deploy the commits made on github
Is there and way to do those, so that if i commit a change the it should be updated in Google Cloud Programs
I tried Google open cloud source repositories but didn't work
I tried GitHub Actions as mentioned by #Ismail and it worked for me
# This is a basic workflow to help you get started with Actions
name: Upload to Google Cloud App Engine
# Controls when the action will run.
on:
# Triggers the workflow on push or pull request events but only for the master branch
push:
branches: [ master ]
pull_request:
branches: [ master ]
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout#v2
- name: Set up Cloud SDK
uses: google-github-actions/setup-gcloud#master
with:
project_id: myid
service_account_key: ${{ secrets.GCP_AUTHCode }}
export_default_credentials: true
- id: Deploy
name: Deploy to App Engine
uses: google-github-actions/deploy-appengine#main
with:
project_id: myid
- uses: actions/setup-node#v1
with:
node-version: 12
- run: npm install
- run: npm install pm2 -g
- run: pm2 start index.js --watch
You can automate App Engine deployments with Cloud Build. Study and follow this GitHub App trigger guide.
With regards to build configuration, you can use this sample build config file (cloudbuild.yaml):
steps:
- name: "gcr.io/cloud-builders/gcloud"
args: ["app", "deploy"]
timeout: "1600s"
This configuration will make Cloud Build run gcloud app deploy on your repo whenever you push commits. The step will timeout if the deployment takes 27 minutes but you're free to change it.
As additional reference, here's another guide on how to automate app deployment with Cloud Source Repositories.
To summarize, you need to enable Cloud Build on your project to use its trigger feature and it will build your app from source then deploy based on your build config.
I'm new to google cloud and I'm trying my best to implement CI / CD on a simple MERN stack application.
I was able to set up google cloud build and get the deploy with automatic triggers (from github branch) to work.
I have only one question: in the cloudbuild.yaml file I have inserted several steps, to do first npm install, then npm build and finally deploy. The process is quite slow and it also copies all the code to the server, not just the build folder.
I would like to understand how to configure the file to be able to use the build folder already present in the github repository and do the deploy directly, without further steps.
On the frontend I use react, the only thing I have to do is serve the static index.html file.
Here is my current configuration (only the frontend, to understand)
steps:
# Step 0: FRONTEND npm install
- name: "gcr.io/cloud-builders/npm"
dir: 'frontend'
args: ['install']
timeout: "5m"
# Step 1: FRONTEND optimized build
- name: "gcr.io/cloud-builders/npm"
dir: 'frontend'
args: ["run", "build"]
timeout: "5m"
# Step 2: FRONTEND Deploy cloud app frontend
- name: "gcr.io/cloud-builders/gcloud"
args: ["app", "deploy", "-v", "0-1-2", "app.yaml"]
dir: 'frontend'
timeout: "20m"
timeout: 60m
In my remote repository I have the build folder ready to use, but I can't figure out how to do the job.
I've also tried something similar to this:
Upload build folder in Google Cloud Build
without success.
One of the problems is that at the end of the process it appears that cloud build is trying to start npm start.
Finally, I am currently using express to simply serve static files.
Using google cloud can I avoid using it and simply configure the handlers from the app.yaml file?
What web server does it use under the hood to serve files if I don't implement express?
If you only need to deploy the build folder, then the link you've provided should do the job. You don't need to run npm install and npm run build unless you want to to copy all your code and create the build folder using Cloud Build.
Credits to #Guillaume (updated, assuming the .yaml file is located at the root directory of the project and build located at a directory called frontend):
steps:
# Step 0: FRONTEND copy only build and deploy cloud app frontend
- name: 'gcr.io/cloud-builders/gcloud'
entrypoint: bash
dir: 'frontend'
args:
- '-c'
- |
cd ..
cp app-production-build.yaml frontend/build
cd frontend/build
gcloud app deploy
timeout: '1600s'
By default, Cloud Build uses a directory named /workspace as a working directory. If you set the dir field in the build step, the working directory is set to /workspace/<dir>. Basically for this build step, Cloud Build's currently on a directory called frontend in the root directory of your project/repo.
Also as Guillaume mentioned, you need to update your app.yaml URL handlers for this to work. I tested this sample inside the build folder of a new React app and it works for me:
runtime: nodejs12
service: frontend-react
handlers:
# Serve all static files with url ending with a file extension
- url: /(.*\..+)$
static_files: \1
upload: (.*\..+)$
# Catch all handler to index.html
- url: /.*
static_files: index.html
upload: index.html
To answer your last question, you can serve static files directly from your app and what you need to do is to configure URL handlers such as static_dir or static_files.
Take note that each file inside build/static are cached to speed up performance so there could be a delay whenever you make several deployments.
Node.js on App Engine Standard doesn't use any webserver under the hood and you have to set it up by specifying it on your package.json. Here's some web frameworks recommended by Google docs.
I have an NPM package hosted on a private Bitbucket git repo (not in the official NPM registry).
I have this in my package.json, under the "dependencies" key:
"a-private-package" git+ssh://git#bitbucket.org:myusername/a-private-package.git
It works when I run npm install locally as my SSH keys are used.
But when I use gcloud app deploy to deploy to the app engine standard environment for node, I get a Host key verification failed from Google Cloud Build.
I have tried:
Adding a custom SSH key to Cloud Build.
https://cloud.google.com/cloud-build/docs/access-private-github-repos
Issue: No access to cloudbuild.yaml for GAE standard; cannot tell git to use the SSH key.
Adding my private git repo to Google Sources.
Issue: No access to cloudbuild.yaml for GAE standard; cannot tell git to use the SSH key.
npm pack; npm install
Issue: Does not keep repo history/URL.
Is it actually possible?
It is not possible to modify the cloudbuild.yaml when you are running gcloud app deploy. Instead, you must create a new cloudbuild.yaml and execute it with gcloud builds submit --config=cloudbuild.yaml . In this case, the gcloud app deploy is going to be executed inside the cloudbuild.yaml.
I have tried the steps described for connecting to a private Github repository and changing the values to fit it with bitbucket, but was not able to. Thus, I have created this Feature Request for better documentation
Using Cloud Source Repositories
I believe that, as you already have a dependency on the private repo, then it will be simpler to host you entire app on it. Given this, you will have to clone the entire repo, run npm install and deploy.
In this case, Cloud Source Repositories has a built in feature to mirror directly to Bitbucket (public and private repos).
Steps:
1) Create on your app root folder a cloudbuild.yaml with the following code:
steps:
# NPM install
- name: 'gcr.io/cloud-builders/npm'
args: ['install']
#Test
- name: 'gcr.io/cloud-builders/npm'
args: ['test']
#Deploy
- name: "gcr.io/cloud-builders/gcloud"
args: ["app", "deploy"]
2) Connect Cloud Source Repositories to Bitbucket
3) Create a Cloud Build Trigger (so new code pushed to the repo will be automatically deployed)
4) Push the root folder containing the app.yaml and the cloudbuild.yaml to the repo
It should now be Synced to Cloud Source Repositories and it should trigger the Cloud Build for the deploy.
Unfortunately you will need to embed a username/password in the package.json, but you can probably use the https endpoint:
"a-private-package": "git+https://myusername:password#bitbucket.org/myusername/a-private-package.git"
If this works for you I'd suggest creating a separate account on bitbucket and restricting it to view-only on that repo.