Deploy gcloud app to diff environments - google-app-engine

I have an app that uses the following command to deploy a static app generated by create-react-app:
gcloud app deploy --project MY_PROJECT -v dev
After that, my app is available on myproject.appstop.com.
But I don't figure out how to deploy this app using a diff URL for each environment. Like.: dev.myproject.appspot.com, stg.myproject.com and so on.
If you know or have other ideas about how to solve this please share your thoughts.

It depends on what you understand by environment. I would definitely recommend you to create different projects for the different environments (my-project-dev, my-project-staging, my-project-test, my-project-prod...)
If you just want to have a different url for your deployment, you are doing ok by using the -v (version parameter).
Once you've deployed again:
gcloud app deploy --project MY_PROJECT -v test
you'll have both versions accessible at:
dev.myproject.appspot.com
test.myproject.appspot.com
Also, check Dan's answer below as it contains very relevant info.

To complement #MarCialR's answer, you can use SSL as well, but with *-dot-* URLs like https://test-dot-myproject.appspot.com, see Targeted routing.
But personally I'm not a big fan of a version-based environment, it brings trouble, see Continuous integration/deployment/delivery on Google App Engine, too risky?
I chose to implement environments at app level - each environment as a different app, each with its own URL. See Advantages of implementing CI/CD environments at GAE project/app level vs service/module level?
Since I'm using a wildcard custom-domain SSL certificate I'm simply mapping the different apps (environments) to different hosts/subdomains in my custom domain - thus ensuring everything works as expected with a custom domain at every point in the CI/CD pipeline, no surprises in production.

Related

GAE: No longer able to update my Gaelyk project due to appcfg losing support

Recently tried to update my Gaelyk project (yes, it's old, but it works well and I still use it), but Google App Engine will no longer accept the update. The error message returned is "Deployments using appcfg are no longer supported. See https://cloud.google.com/appengine/docs/deprecations". The thing is, I never used appcfg to deploy my application; I used Gaelyk and Gradle. But obviously Gaelyk must have used appcfg under the covers.
I did download the replacement Google Cloud SDK, but this new tool is not similar at all to how Gaelyk and Gradle worked. Is there anything I can do to get Gaelyk to work anymore? Or is Gaelyk just dead and I need to rewrite my application (like in Node.js or something instead of Groovy).
This will be hard, however I will try to help you as possible. I think you may try to migrate it somehow to app.yaml configuration of GAE.
I am not sure what plugins are used in the project. From Gaelyk temple project I can see that it's using appengine-geb which, according to the documentation, behind the scenes, is using gradle-appengine-plugin (there is wrong link on this doc, but proper is bellow).
On the github of gradle-appengine-plugin I have found following.
There is a note:
NOTE: All App Engine users are encouraged to transition to the new
gradle plugin for their projects.
And in FAQ part there is following information:
How do I deploy with gcloud?
If you're using gcloud to deploy your application, the newest version of app deploy > doesn't support war
directories, you will need to provide it with an app.yaml OR you can
use the appengineStage task to create a directory that is deployable
in /build/staged-app
$ ./gradlew appengineStage
$ gcloud app deploy build/staged-app/app.yaml --project [app id]
--version [some version]
NOTES:
You must explicitly define all config files your want to upload
(cron.yaml, etc)
This does not work with EAR formatted projects.
I think the best option will be to migrate to new appenine plugin or if not possible try to implement is with gcloud app deploy command crating the config files manually (at least app.yaml). And for this migration I can provide you this document.
I hope you will manage somehow...
I can confirm that Serge's answer on the Gaelyk Groups site works; the same procedure that he figured out also worked for me. To summarize:
Run gradlew appengineRun as run previously with Gaelyk.
Copy all jar files inside the build\exploded-app\WEB-INF\lib folder into a \src\main\webapp\web-inf\lib folder (for me the new lib folder did not exist previously).
To deploy, use the new required gcloud tool, and instead of running gradlew appengineUpdate (which fails now), instead run
gcloud app deploy appengine-web.xml where that XML file can be found in your webapp/WEB-INF directory. I navigated to that directory to run the gcloud command, but you can use a relative path there if your working directory is elsewhere. (There are a number of optional flags associated with the gcloud app deploy command, but I didn't need any of them.)
Serge needed to use these instructions to convert datastore-indexes.xml to index.yaml and run gcloud app deploy index.yaml, however, I didn't need to do this because I had no datastores.

Can I have application versions in python27 and python37 in Google App Engine Standard (both types)

I want to test Python 3.7 on Google App Engine Standard.
I am afraid if I upload application with python37 old application will stop working and will be no revert to previous python27.
Can you share some experience if it possible to keep both runtime versions?
It is not clear for me.
I read Python 3.7 on Google App Engine - documentation but not found information.
You have 3 main options, ranked from easier to 'harder' to do:
Just deploy this test you want to do in a new project, and you don't have to worry about your old application getting replaced.
Deploy this test to a new service. Just add the line service: whatevername to the app.yaml file of your test, and deploy it as usual with $gcloud app deploy. VoilĂ , you have a new service.
You can deploy this test in your default service, but to avoid stopping the previous one, add the --no-stop-previous-version flag to your $ gcloud app deploy command. After that, you can split traffic between this test and your actual app.
To be honest, I would go with options 1 or 2, as they are far more simple to deploy, and you can later on delete the test project or delete the new service if you wish to.

Create-React-App + Heroku: Development, Staging and Production environments

I'm developing an app (front-end app that consumes an API) based on the create-react-app package. I'm using Heroku to deploy and currently have two deployments based on the same codebase, staging and production. These deployments should use different development/staging/production APIs that have different databases.
Is it possible to tell create-react-app to use different env variables based on how I run react-scripts start?
env.development
REACT_API: https://localhost/react_api
env.staging
REACT_API: https://myappstagingapi.heroku.com
env.production
REACT_API: https://myappproductionapi.heroku.com
How would I do this? And is this a good workflow?
Thank you very much!
I had the similar situation having more environments than production and development while deployment was done automatically from Github.
First of all, make sure you are using the deployment buildpack i.e.
https://github.com/mars/create-react-app-buildpack.git
You can add this URL in Settings in your project on Heroku, replacing NodeJS default buildpack for instance.
Full documentation is here:
https://elements.heroku.com/buildpacks/nhutphuongit/create-react-app-buildpack
If you follow the link above, you can see the chapter Environment variables. So, in order that your React App can process custom variables:
Add a one that suits you with REACT_APP_ prefix to your Heroku project environment variables (through Settings in Heroku Dashboard) Note that only the envs with this prefix will be visible in your process.env later so you should amend your code accordingly
Redeploy the application.
This should make the things work. I am sure it is also possible to keep .env file but I prefer to have more control via Heroku Dashboard.

Is it possible to customize gcloud app deploy?

I'd like to perform some preliminary checks before running the actual deployment to AppEngine. It would be nice to put some Python find in the repository, so that gcloud would behave similarly for everyone. Does gclould provide some means for this kind of customization? Can't find this in the official docs.
No, there are no hooks in gcloud app deploy. But you could pretty easily write a small Python script to wrap the call to gcloud using e.g. the subprocess module and have all of your users deploy via that script.

How to deploy one app engine app to multiple projects

My problem is that I want to create dev, stage, prod environments by using different GCP projects.
Basically they are running the same code, just running them in different isolated environments.
I'm using gcloud app deploy in command line to deploy app right now.
How can I efficiently deploy an app to different project?
Do I have to do gcloud init to change my configuration of default project every time?
There must be some better practices.
Or, is there a better way for me to set up dev... environments in the context of app engine?
Thanks.
Instead of using gcloud init to change your configuration each time, use this code to deploy to multiple projects faster:
gcloud app deploy -q --project [YOUR_PROJECT_ID]
If your projects have similar IDs, let's say: test1, test2, test3, test4, You can deploy to the four projects with one command. Use this code:
for i in {1..4}; do gcloud app deploy -q --project test${i}; done
The "standard" approach is to use versions, e.g.
qa.myApp.appspot.com
Once a version is ready for next step, you deploy it with a different version id.
One problem with using multiple projects is that you have to maintain a different data set for each project.
My preference is to have the different environments managed via the same version control as the code - one branch for each environment, keeping the deployments perfectly aligned with the natural flow of code changes, promoted via branch merges: dev -> stage -> production.
To minimize the risk of human error I try as much as possible to keep the deployment configs in the code itself (i.e. - have the app IDs, versions, etc. picked up from the .yaml files, not passed to the deploy cmd as args). The deployment cmds themselves are kept in a cheat-sheet file (too simple to warrant a full-blown script at this time), also git-controlled. Illustrated in this answer: https://stackoverflow.com/a/34111170/4495081
Deployments are done from separate, dedicated workspaces - one for each environment, based on the corresponding git branch (I never switch the branches in these workspaces). I just update the workspace corresponding to the desired environment to the version needed and copy-paste the deployment cmd from the workspace's cheat-sheet.
This model is IMHO CI/CD-ready and can easily be entirely automated.
For Python applications, you can set application in the app.yaml file. This allows you to use different data for each project. This is when you deploy using the appcfg.py command.
application: myproject
version: alpha-001
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /
script: home.app
If you don't want to change the application value in this file for each project, you can run the following:
appcfg.py -A <YOUR_PROJECT_ID> -V v1 update myapp/
https://cloud.google.com/appengine/docs/python/config/appref
If you do not specify the application in the file, use the --application option in the appcfg command when you deploy. This element is ignored when you deploy using the gcloud app deploy command.

Resources