What are the applicable 'cloudbuild.yaml' steps to deploy a Java App to Google App Engine Standard edition? - google-cloud-build

What are the applicable 'cloudbuild.yaml' steps to deploy a Java App to Google App Engine Standard edition?
I cannot find anything specific to this in the documentation.
I am trying:
steps:
- name: 'gcr.io/cloud-builders/mvn'
args: [ 'install', '--settings', 'settings.xml' ]
- name: 'gcr.io/cloud-builders/gcloud'
args: [ 'app', 'deploy' ]
timeout: '6m0s'
The first step succeeds but the second step fails with this less-than-helpful message:
Already have image (with digest): gcr.io/cloud-builders/gcloud
ERROR: gcloud crashed (AttributeError): 'NoneType' object has no attribute 'endswith'
Should I use the maven deploy command 'mvn appengine:deploy' instead?
Thank you in advance.
A second attempt:
steps:
- name: 'gcr.io/cloud-builders/mvn'
args: [ '--define', 'skipTests', '--settings', 'settings.xml',
'clean', 'package', 'appengine:deploy' ]
timeout: '6m0s'
With this result:
Execution default-cli of goal
com.google.cloud.tools:appengine-maven-plugin:1.3.1:deploy
failed:
The Google Cloud SDK could not be found
in the customary locations and no path was provided.

I found the answer at:
https://medium.com/#Leejjon_net/use-cloud-build-to-do-continuous-delivery-for-your-java-project-on-app-engine-3c59072547ca
steps:
- id: 'Stage app using mvn appengine plugin'
name: 'gcr.io/cloud-builders/mvn'
args: [ '--define', 'skipTests', '--settings', 'settings.xml', 'package', 'appengine:stage' ]
- id: 'Deploy to app engine'
name: 'gcr.io/cloud-builders/gcloud'
args: [ 'app', 'deploy', 'target/appengine-staging/app.yaml' ]
Also, make sure version of plug in is:
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>2.2.0</version>
</plugin>

Related

Gradle build failed in Tekton CI/CD

I have below pipeline task for Gradle build, which clones the project from bitbucket repo and try to build the application.
tasks:
- name: clone-repository
taskRef:
name: git-clone
workspaces:
- name: output
workspace: shared-workspace
params:
- name: url
value: "$(params.repo-url)"
- name: deleteExisting
value: "true"
- name: build
taskRef:
name: gradle
runAfter:
- "clone-repository"
params:
- name: TASKS
value: build -x test
- name: GRADLE_IMAGE
value: docker.io/library/gradle:jdk17-alpine#sha256:dd16ae381eed88d2b33f977b504fb37456e553a1b9c62100b8811e4d8dec99ff
workspaces:
- name: source
workspace: shared-workspace
I have the below project structure
The settings.gradle contain the below projects
rootProject.name = 'discount'
include 'core'
include 'infrastructure'
include 'shared'
include 'discount-api'
when running the pipeline with below code
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: run-pipeline
namespace: tekton-pipelines
spec:
serviceAccountName: git-service-account
pipelineRef:
name: git-clone-pipeline
workspaces:
- name: shared-workspace
persistentVolumeClaim:
claimName: fetebird-discount-pvc
params:
- name: repo-url
value: git#bitbucket.org:anandjaisy/discount.git
Getting an exception as
FAILURE: Build failed with an exception.
* What went wrong:
Task 'build -x test' not found in root project 'discount'.
I have used the task from the Tekton catalog https://github.com/tektoncd/catalog/blob/main/task/gradle/0.1/gradle.yaml
If I pass the PROJECT_DIR value as ./discount-api to the Gradle task. I get an exception as settings.gradle not found. which is correct because that project has no setting.gradle file.
The main project is discount-api. I need to build the application. Quite not sure what is wrong. On the local env if I do ./gradlew build in the root directory the application successfully builds.
The error message tells about Task 'build -x test' not found in root project 'discount'
Checking that Task, in tekton catalog, we can read:
....
- name: TASKS
description: 'The gradle tasks to run (default: build)'
type: string
default: build
steps:
- name: gradle-tasks
image: $(params.GRADLE_IMAGE)
workingDir: $(workspaces.source.path)/$(params.PROJECT_DIR)
command:
- gradle
args:
- $(params.TASKS)
Now, in your Pipeline, you set that TASKS param to build -x test. This is your issue.
As you can read above, that TASKS param is a string. While you want to use an array.
You should be able to change the param definition, such as:
....
- name: TASKS
description: 'The gradle tasks to run (default: build)'
type: array
default:
- build
steps:
- name: gradle-tasks
image: $(params.GRADLE_IMAGE)
workingDir: $(workspaces.source.path)/$(params.PROJECT_DIR)
command:
- gradle
args: [ "$(params.TASKS)" ]
This would ensure "build", "-x" and "test" are sent to gradle as separate strings. While your current attempt would be equivalent to running gradle "build -x test", resulting in your error.

GCP cloudbuild with multiple steps

I have the below steps and referring to the steps from here https://cloud.google.com/build/docs/building/build-java#gradle
Now for the second and third steps I don't need a gradle docker image. If I add I can see on the build logs the image already exists. How can
steps:
# This step show the version of Gradle
- name: gradle:7.4.2-jdk17-alpine
entrypoint: gradle
args: ['--version']
# This step build the gradle application
- name: 'Build'
entrypoint: gradle
args: [ 'build' ]
# This step run test
- name: 'Test'
entrypoint: gradle
args: [ 'test' ]

Github Actions running both .Net Core and Ant Design Pro

I want to be able to run both .NET core and ant design pro (React) using Cypress Github Actions but however, I have the problem below:
Problem:
Error message: AssertionError: Timed out retrying after 4000ms: Expected to find element: .ant-pro-table-list-toolbar-right > :nth-child(1) > .ant-space > [style=""] > .ant-btn, but never found it.
It was running smoothly on localhost but couldn't work on github actions. Steps that I took to run locally:
type "dotnet run"
type "yarn start"
and it is able to run locally.
cypress.js
describe('test button', () => {
it('Create application',() => {
cy.visit('http://localhost:8000/Application')
cy.get('.ant-pro-table-list-toolbar-right > :nth-child(1) > .ant-space > [style=""] > .ant-btn').click()
}
main.yml
name: Cypress
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
Build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout#v2
- name: Setup .NET
uses: actions/setup-dotnet#v1
with:
working-directory: dotnet
dotnet-version: 5.0.404
run: dotnet run --no-restore
- name: Cypress tests
uses: cypress-io/github-action#v2
with:
working-directory: my-app
browser: chrome
record: true
build: yarn run build
start: yarn start
wait-on: 'http://localhost:8000'
env:
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
DEBUG: "#cypress/github-action"
Hope to have someone to help.

Difference between PUT and OUTPUT steps in Concourse

Could someone tell me the difference between the PUT step and the OUTPUT step in Concourse? For example, in the following type of YAML files why do we need a put step after a get? Can't we use output instead of put? If not what are the purposes of each two?
jobs:
- name: PR-Test
plan:
- get: some-git-pull-request
trigger: true
- put: some-git-pull-request
params:
context: tests
path: some-git-pull-request
status: pending
....
<- some more code to build ->
....
The purpose of a PUT step is to push to the given resource while an OUTPUT is the result of TASK step.
A task can configure outputs to produce artifacts that can then be propagated to either a put step or to another task step in the same plan.
This means that you send the resource that you are specifying on the GET step to the task as an input, to perform wherever build or scripts executions and the output of that task
is a modified resource that you can later pass to your put step or to another TASK if you don't want to use PUT.
It would also depend on the nature of the defined resource in your pipeline. I'm assuming that you have a git type resource like this:
resources:
- name: some-git-pull-request
type: git
source:
branch: ((credentials.git.branch))
uri: ((credentials.git.uri))
username: ((credentials.git.username))
password: ((credentials.git.pass))
If this is true, the GET step will pull that repo so you can use it as an input for your tasks and if you use PUT against that same resource as you are describing in your sample code, that will push changes to your repo.
Really it depends on the workflow that you want to write but to give an idea it would look something like this:
jobs:
- name: PR-Test
plan:
- get: some-git-pull-request
trigger: true
- task: test-code
config:
platform: linux
image_resource:
type: docker-image
source:
repository: yourRepo/yourImage
tag: latest
inputs:
- name: some-git-pull-request
run:
path: bash
args:
- -exc
- |
cd theNameOfYourRepo
npm install -g mocha
npm test
outputs:
- name: some-git-pull-request-output
Then you can use it on either a PUT
- put: myCloud
params:
manifest: some-git-pull-request-output/manifest.yml
path: some-git-pull-request-output
or a another task whitin the same plan
- task: build-code
config:
platform: linux
image_resource:
type: docker-image
source:
repository: yourRepo/yourImage
tag: latest
inputs:
- name: some-git-pull-request-output
run:
path: bash
args:
- -exc
- |
cd some-git-pull-request-output/
npm install
gulp build
outputs:
- name: your-code-build-output
Hope it helps!

CircleCI: Create Workflow with separate jobs. One build and different Deploys per environment

everyone. I need some help with some issues that I am facing configuring circleCi for my Angular project.
The config.yml that I am using for a build and deploy process is detailed below. Currently I have decided to do separate jobs for each environment and each one includes the building and deploy. The problem with this approach is that I am repeating myself and I can't find the correct way to deploy an artifact builded in the previous job for the same workflow.
version: 2
jobs:
build:
docker:
- image: circleci/node:8-browsers
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package.json" }}
- run:
name: Install dependencies
command: npm install
- save_cache:
key: dependency-cache-{{ checksum "package.json" }}
paths:
- .node_modules
- run:
name: Build Application (Production mode - aot enabled)
command: npm run build:prod
- store_artifacts:
path: dist
destination: dist
deploy_prod:
docker:
- image: circleci/node:8-browsers
environment:
- FIREBASE_TOKEN: "1/AFF2414141ASdASDAKDA4141421sxscq"
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package.json" }}
- run:
name: Install dependencies
command: npm install
- save_cache:
key: dependency-cache-{{ checksum "package.json" }}
paths:
- .node_modules
- run:
name: Build Application (Production mode - aot enabled)
command: npm run build:prod
- store_artifacts:
path: dist
destination: dist
- run:
command: ./node_modules/.bin/firebase use default
- deploy:
command: ./node_modules/.bin/firebase deploy --token=$FIREBASE_TOKEN
deploy_qa:
docker:
- image: circleci/node:8-browsers
environment:
- FIREBASE_TOKEN: "1/AFF2414141ASdASDAKDA4141421sxscq"
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package.json" }}
- run:
name: Install dependencies
command: npm install
- save_cache:
key: dependency-cache-{{ checksum "package.json" }}
paths:
- .node_modules
- run:
name: Build Application (Production mode - aot enabled)
command: npm run build:prod
- store_artifacts:
path: dist
destination: dist
- run:
command: ./node_modules/.bin/firebase use qa
- deploy:
command: ./node_modules/.bin/firebase deploy --token=$FIREBASE_TOKEN
workflows:
version: 2
build-and-deploy:
jobs:
- build:
filters:
branches:
only:
- master
ignore:
- /feat-.*/
- deploy_prod:
filters:
branches:
ignore:
- /.*/
tags:
only:
- /v[0-9]+(\.[0-9]+){2}/
- deploy_qa:
filters:
branches:
ignore:
- /.*/
tags:
only:
- /v[0-9]+(\.[0-9]+){2}-BETA-([0-9]*)/
I understand that each job is using a different docker image, so this prevents me work on the same workspace.
Q: How can I use the same docker image for different jobs in the same workflow?
I included the store_artifacts thinking it could help me, but what I read about it is that it only works for using through the dashboard or the API.
Q: Am I able to recover an artifact on a job that requires a different job that stored the artifact?
I know that I am repeating myself, my goal is to have a build job required for a deploy job per environment depending on the tags' name. So my deploy_{env} jobs are mainly the firebase commands.
workflows:
version: 2
build-and-deploy:
jobs:
- build:
filters:
branches:
only:
- master
ignore:
- /feat-.*/
tags:
only:
- /v[0-9]+(\.[0-9]+){2}/
- /v[0-9]+(\.[0-9]+){2}-BETA-([0-9]*)/
- deploy_prod:
requires:
- build
filters:
branches:
ignore:
- /.*/
tags:
only:
- /v[0-9]+(\.[0-9]+){2}/
- deploy_qa:
requires:
- build
filters:
branches:
ignore:
- /.*/
tags:
only:
- /v[0-9]+(\.[0-9]+){2}-BETA-([0-9]*)/
Q: What are the recommended steps (best practices) for this solution?
Q: How can I use the same docker image for different jobs in the same workflow?
There might be two methods of going about this:
1.) Docker Layer Caching: https://circleci.com/docs/2.0/docker-layer-caching/
2.) Caching the .tar file: https://circleci.com/blog/how-to-build-a-docker-image-on-circleci-2-0/
Q: Am I able to recover an artifact on a job that requires a different
job that stored the artifact?
The persist_to_workspace and attach_workspace keys should be helpful here: https://circleci.com/docs/2.0/workflows/#using-workspaces-to-share-data-among-jobs
Q: What are the recommended steps (best practices) for this solution?
Not sure here! Whatever works the fastest and cleanest for you. :)

Resources