Deploy Ruby on Rails app to App Engine using Cloud Build - ruby-on-rails

I'm trying to automate the deployment of a Ruby on Rails app to App Engine using Cloud Build.
My app.yaml looked like this,
runtime: ruby
env: flex
entrypoint: bundle exec rails server
But I'm getting this error,
Step #1: ERROR: (gcloud.app.deploy) There is a cloudbuild.yaml in the current directory, and the runtime field in /workspace/app.yaml is currently set to [runtime: ruby]. To use your cloudbuild.yaml to build a custom runtime, set the runtime field to [runtime: custom]. To continue using the [ruby] runtime, please remove the cloudbuild.yaml from this directory.
Then I tried to change the runtime to custom and add a Dockerfile as custom runtime needs a Dockerfile.
But now I'm getting an error saying,
ERROR: (gcloud.app.deploy) A custom runtime must have exactly one of [Dockerfile] and [cloudbuild.yaml] in the source directory; [/home/milindu/Projects/ElePath-Ruby] contains both
Then I removed Dockerfile also. But now getting into this weird situation. You can see the 'Step #1:' is growing into several like stuck in a recursion.

Cloudbuild.yaml should work with App Engine Flexible without the need to use a custom runtime. As detailed in the first error message you received, you cannot have an app.yaml and the cloudbuild.yaml in the same directory if you are deploying in a non-custom runtime, to remedy the situation, follow these steps:
Move your app.yaml and other ruby files into a subdirectory (use your
original app.yaml, no need to use custom runtime)
Under your cloudbuild.yaml steps, modify the argument for app deploy
by adding a third one specifying your app.yaml's path.
Below is an example:
==================FROM:
steps:
- name: 'gcr.io/cloud-builders/gcloud'
args: ['app', 'deploy']
timeout: '1600s'
===================TO:
steps:
- name: 'gcr.io/cloud-builders/gcloud'
args: ['app', 'deploy', '[SUBDIRECTORY/app.yaml]']
timeout: '1600s'

Related

How to change the env file content when build the sapui5 application via #ui5/cli

I'm now working on sapui5 project managed by ui5.yaml & #ui5/cli. I don't know how to use something like .env to control some variables' value which can be switched between dev env and pro env.
And i have found a workaround, which creating a env.js and include it into controller file. So i can change some value by editing the env.js file. And now i want to make it more convenient.
I use #ui5/cli ui5 run build to build the project. And there is a configuration for custom tasks. And there is a task called webide-extension-task-copyFile which used to copy the /xs-app.json.
And now i create three env files which named as env-dev.js env-pro.js env.js. And i want to copy the env-pro into the env.js before it is built. And copy the env-dev into env.js when i run the ui5 run serve.
I have the config in ui5.yaml like this
specVersion: '2.4'
metadata:
name: ui
type: application
framework:
name: SAPUI5
....
customTasks:
....
- name: webide-extension-task-copyFile
afterTask: webide-extension-task-resources
configuration:
srcFile: '/webapp/env/env-pro.js'
destFile: '/webapp/env/env.js'
I'm sure the task has been triggered, but the file content hasn't been changed. So could someone can help me, or has another idea or success example about using the env in ui5 project.
Thank you :)

Maven upgrade unable to run package appengine:stage

I have a Java 8 Spring Boot app that is deployed to Google App Engine and being built via GCP CloudBuild. I am trying to upgrade it from Java 8 to Java 11.
In the cloudbuild.yaml file, I changed:
- id: 'Build and Test'
name: 'gcr.io/cloud-builders/mvn:3.5.0-jdk-8'
args: ['package', 'appengine:stage']
to:
- id: 'Build and Test'
name: 'maven:3.8.3-jdk-11'
args: ['package', 'appengine:stage']
When I run the CloudBuild, this step now suddenly fails with the following error:
docker.io/library/maven:3.8.3-jdk-11
/usr/local/bin/mvn-entrypoint.sh: 50: exec: package: not found
In its previous configuration, it was running just fine. The entire cloudbuild.yaml file is:
steps:
- id: 'copy file'
name: 'ubuntu'
args: ['cp', 'src/main/appengine/app.yaml', src/main/appengine/app.yaml]
- id: 'Build and Test'
name: 'maven:3.8.3-jdk-11'
args: ['package', 'appengine:stage']
What is going on here? Does the gcr.io/cloud-builders/mvn:3.5.0-jdk-8 image somehow understand mvn package appengine:stage, whereas the maven:3.8.3-jdk-11 image doesn't? Mainly I just need someone to help me understand why I'm getting the error. If anyone could also lend some suggestions for how to fix or circumvent it, that'd be greatly appreciated as well. Thanks in advance!
Reviewing Google documentation about migrating to the Java 11 runtime, I found that App Engine standard environment allows you to use several of App Engine's packaged services and APIs in the Java 11 runtime, reducing runtime conversion effort and complexity.
The Project Engine API JAR allows your Java 11 app to contact the bundled services APIs and access most of the same functionality as the Java 8 runtime.
You can also use Google Cloud products that are equivalent to the App Engine packaged services in functionality.
Adding overview of the migration process documentation.
The process to follow is:
Download Cloud SDK.
Migrate from the standalone App Engine Maven plugin to the Cloud
SDK-based Maven plugin or the Cloud SDK-based Gradle plugin.
Install the App Engine API JAR if you are using the App Engine
bundled services.
Migrate your XML files to the equivalent yaml files.
Now, regarding the issue you are getting, you should specify the whole path of the script because /usr/src/app may not be in your path. You must also ensure that your entrypoint.sh is executable; however, depending on your circumstance, docker will duplicate the permissions precisely as they are on your build host, so this step may not be necessary.
Additional suggestion is that you can't use single quotes ' for the entrypoint/command, you can try with “,
It was so obvious in hindsight. I needed to specify mvn as the entrypoint command in the step like so:
- id: 'Build and Test'
entrypoint: mvn
name: 'maven:3.8.3.0-jdk-11'
args: ['package','appengine:stage']

iOS Sourcery with Flutter build

Im trying to build my flutter app for iOS it has a google maps key that I want to protect and not check in to source control it needs to be buildable from azure, to achieve this I'm storing my maps key as a secret variable in azure and as a system environment variable locally, I'm using Sourcery https://github.com/krzysztofzablocki/Sourcery to generate a class for me that contains this key, it all works but only the second time I build, the first build always fails.
So I'm building using this command
flutter build ios --flavor dev --verbose
Which the first run will give me the error
error: Build input file cannot be found:
'/Users/martin/xxx/xxx/xxx/ios/Runner/Credentials.generated.swift' (in target
'Runner'
Then issuing the same command again
** BUILD SUCCEEDED **
this is my run script its called before compile sources and after the flutter run script
this calls my script which calls another script to export the map api key and runs sourcery command using a .yml file as its config heres the script, (it also does some logging)
#!/bin/bash
echo "Generate Credentials Code"
CREDENTIALS_DIR="$SRCROOT/credentials"
# Set credentials if local script for adding environment variables exist
if [ -f "$CREDENTIALS_DIR/add_credentials_to_env.sh" ]; then
echo "Add credentials to environement"
source "$CREDENTIALS_DIR/add_credentials_to_env.sh"
echo "finished running add_credentials_to_env.sh"
fi
echo "RUN SOURCERY"
$SRCROOT/Pods/Sourcery/bin/sourcery --config "$SRCROOT/config.yml"
echo "FINISHED RUNNING SOURCERY"
for file in "$SRCROOT/Runner"/*; do
echo "$file"
done
and here is my config file
sources:
- .
project:
file: Runner.xcodeproj
target:
name: Runner
module: Runner
templates:
- credentials/Credentials.stencil
output:
path: ./Runner/
link:
project: Runner.xcodeproj
target: Runner
args:
mapsApiKey: ${MAPS_API_KEY_IOS}
this generates my class correctly on the first build and seems to be added correctly to the target (edited out my key) but the app will only compile if I run the build command again.
// Generated using Sourcery 1.4.2 — https://github.com/krzysztofzablocki/Sourcery
// DO NOT EDIT
public struct Credentials {
let mapsApiKey: String
}
public let credentials = Credentials(mapsApiKey:
"xxxxxxxxxxMY_KEYxxxxxxxxxxx")
Any ideas?
xcode 12.5 m1 macbook pro, swift 5
Looks like you generate the file too late. I'll suggest move your script to Aggregate and add it as a dependency to your target
Add Aggregate
Move your script to 'Run script' section
Add 'PreBuildScriptsRunner' as a dependency to your application target, make sure 'Dependencies' section on top of all other sections
Manually setting environment variables is an annoying thing developers would have to do on their own machines, and there are nicer/ more common ways of setting up private keys. After a few years of using environment variables/ bash, it still causes issues which are not easily detectable. You may want to automate/ document it, but then you have to consider developers using zsh, fish vs. bash? Also, I try to avoid using Xcode build phases where possible.
Solution? (This is what I have)
Why don't you use your CI (Azure pipeline?, I use Github workflows) to write a Xcode build configuration file (not a Swift file). The sensitive keys could be in a file Secrets.xcconfig, which is added to your Xcode as a build configuration. Then, in your Info.plist of your application, and your code can load them.
Create a file, Secrets.xcconfig:
SECRET_API_KEY = 12312rfiwhvde.wvascafsf.df325
Add it to your Xcode project, and then to the project's build configuration:
Add Secrets.xcconfig to your .gitignore
Make sure to git ignore the file before committing it to the repo. You can also keep an Example.Secrets.xcconfig which users can use. In the readme, tell users to run cp Example.Secrets.xcconfig Secrets.xcconfig and then to update values in it. Now you can clearly see what keys the application is using (its clearly in the directory). As a bonus, you can add this file the Xcode project, so that when the file is missing, it shows up in red (indicating to the user they really should acquire this file somehow):
In Info.plist, reference the variable:
<dict>
<key>SECRET_API_KEY</key>
<string>$(SECRET_API_KEY)</string>
</dict>
In your code, load the variable that was stored in Info.plist:
let key = Environment.infoDictionary["SECRET_API_KEY"] as? String
In your CI/ Azure pipeline:
Run echo "SECRET_API_KEY = $SECRET_API_KEY_SAVED_IN_CONTINUOUS_INTEGRATION" >> Secrets.xcconfig
Then you can just .gitignore the file instead of setting environment variables. When you work with other developers, you just give them this file, and nothing else needs to be done to build locally.
So I have answered your question not by solving your direct problem, but giving you a more common/ canonical way of solving this problem that many developers have faced before.

Not able to use linterconfigs command

I want to use Schemacrawler lint in my project and wants to use custom lints only. Based on documentation , it says we can use command -linterconfigs=[path to linter XML configuration file] But when I tried creating XML configuration file and use the custom lints only, I still see default linters are running. Am I doing anything wrong ?
Here is the steps I followed:
download and unzip the package
create dump database named example.database
created schemacrawler-linter-configs.xml with one of the existing lint
Using following command to run the lint on dump database from _schemacrawler directory
./schemacrawler.sh --server=postgresql -command=lint -linterconfigs=schemacrawler-linter-configs.xml -database=example.database
Rashmi, SchemaCrawler runs all linters by default. You need to turn off any linters you don't need in the linters config file. Here is an example of how you can do it:
<schemacrawler-linter-configs>
<linter id="schemacrawler.tools.linter.LinterForeignKeyMismatch">
<run>false</run>
</linter>
</schemacrawler-linter-configs>
Sualeh Fatehi, SchemaCrawler

Deploy to Google App Engine Flex environment from Google Cloud Build using Dockerfile

I have a Google App Engine Flex project, which contains the following files:
app.yaml - to define the App Engine Flex environment
Dockerfile - based on a Google App Engine container with some additions
cloudbuild.yaml
cloudbuild.yaml content:
steps:
- name: 'gcr.io/cloud-builders/docker'
args: ['build', '--tag=gcr.io/$PROJECT_ID/<projectname>', '.']
- name: 'gcr.io/cloud-builders/gcloud'
args: ['app', 'deploy']
timeout: '1600s'
images: ['gcr.io/$PROJECT_ID/<projectname>']
This is based on the docs at:
https://cloud.google.com/cloud-build/docs/configuring-builds/build-test-deploy-artifacts#deploying_artifacts
I'm getting the following error on the app deploy command:
A custom runtime must have exactly one of [Dockerfile] and [cloudbuild.yaml] in the source directory
Without cloudbuild.yaml it doesn't know to try and deploy the app, without the Dockerfile it doesn't know what is in it, so how do I specify the same workflow with only one of these?
I ran into the same issue working on a Django project on a flex app engine with a custom docker file. I moved all project files except couldbuild.yaml into a subfolder and in the cloudbuild.yaml specified the subfolder like so
steps:
- name: "gcr.io/cloud-builders/gcloud"
args: ["app", "deploy", "<subfolder>/app.yaml"]
timeout: "1600s"
That worked for me.
(see also does appengine cloudbuild.yaml requires a custom runtime?)
My approach was the other way around. Put the cloudbuild configuration in a subfolder and use the --config="<folder>

Resources