From f0f5f2c694598d99f74d3b3cfe6dd7da135c0393 Mon Sep 17 00:00:00 2001 From: Marcos Lopez Date: Sun, 24 Nov 2024 19:27:29 -0300 Subject: [PATCH 1/6] fix: fixe cleanup images --- .github/workflows/mainClient.yml | 24 ++++++++++++++++++++++++ .github/workflows/mainServer.yml | 5 +---- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/.github/workflows/mainClient.yml b/.github/workflows/mainClient.yml index b81a194e..dc9df59a 100644 --- a/.github/workflows/mainClient.yml +++ b/.github/workflows/mainClient.yml @@ -63,6 +63,30 @@ jobs: run: | docker push $GCLOUD_REGION-docker.pkg.dev/${{ secrets.GCLOUD_PROJECT_ID }}/klowhubnext-client/klowhub-client:${{ github.sha }} + # 6.5. Limpiar imágenes antiguas + - name: Cleanup Old Images + working-directory: ./client + run: | + TAGS=$(gcloud container images list-tags \ + ${{ secrets.GCLOUD_REGION }}-docker.pkg.dev/${{ secrets.GCLOUD_PROJECT_ID }}/klowhubnext-client/klowhub-client \ + --format='get(tags)' \ + --sort-by=~TIMESTAMP) + + TOTAL_IMAGES=$(echo "$TAGS" | wc -l) + if [ $TOTAL_IMAGES -gt 2 ]; then + TO_DELETE=$((TOTAL_IMAGES - 2)) + + echo "Found $TOTAL_IMAGES images, keeping 2, deleting $TO_DELETE" + echo "$TAGS" | tail -n $TO_DELETE | while read TAG; do + if [ ! -z "$TAG" ]; then + echo "Deleting image with tag: $TAG" + gcloud container images delete \ + "${{ secrets.GCLOUD_REGION }}-docker.pkg.dev/${{ secrets.GCLOUD_PROJECT_ID }}/klowhubnext-client/klowhub-client:$TAG" \ + --quiet + fi + done + fi + # 7. Desplegar a Cloud Run - name: Deploy to Cloud Run working-directory: ./client diff --git a/.github/workflows/mainServer.yml b/.github/workflows/mainServer.yml index bc5f8ceb..0b085815 100644 --- a/.github/workflows/mainServer.yml +++ b/.github/workflows/mainServer.yml @@ -30,7 +30,7 @@ jobs: GATEWAY_SERVICE_PORT: 3000 UPLOAD_SERVICE_NAME: klowhub-upload-api UPLOAD_SERVICE_PORT: 3003 - MAX_IMAGES_TO_KEEP: 2 + MAX_IMAGES_TO_KEEP: 1 steps: - uses: actions/checkout@v4 @@ -293,7 +293,4 @@ jobs: DEPLOY_NAME="${DEPLOY_INFO#*/}" echo "Setting revision history limit for $DEPLOY_NAME" kubectl patch deployment $DEPLOY_NAME -n $NAMESPACE -p '{"spec": {"revisionHistoryLimit": 2}}' - kubectl rollout status deployment/$DEPLOY_NAME -n $NAMESPACE - echo "Current revision history for $DEPLOY_NAME:" - kubectl rollout history deployment/$DEPLOY_NAME -n $NAMESPACE done From c3cbe26b6e534d5b652c21fa64dca14842969ff9 Mon Sep 17 00:00:00 2001 From: Marcos Lopez Date: Sun, 24 Nov 2024 20:09:04 -0300 Subject: [PATCH 2/6] fix: fixe src paths for proto --- server/apps/gateway/src/pubsub/pubsub.module.ts | 2 +- server/apps/gateway/src/upload/upload.module.ts | 2 +- server/k8s/gateway-autoscaler.yml | 15 +++++++++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 server/k8s/gateway-autoscaler.yml diff --git a/server/apps/gateway/src/pubsub/pubsub.module.ts b/server/apps/gateway/src/pubsub/pubsub.module.ts index 58984dad..de14e49a 100644 --- a/server/apps/gateway/src/pubsub/pubsub.module.ts +++ b/server/apps/gateway/src/pubsub/pubsub.module.ts @@ -11,7 +11,7 @@ import { PubSubGatewayService } from './pubsub.gateway.service'; transport: Transport.GRPC, options: { package: 'googlecloudstorage', - protoPath: 'src/proto/upload.proto', + protoPath: '../../protos/upload.proto', url: '0.0.0.0:50051', }, }, diff --git a/server/apps/gateway/src/upload/upload.module.ts b/server/apps/gateway/src/upload/upload.module.ts index 2b18b0da..aa3fce2b 100644 --- a/server/apps/gateway/src/upload/upload.module.ts +++ b/server/apps/gateway/src/upload/upload.module.ts @@ -10,7 +10,7 @@ import { UploadController } from './upload.controllers'; transport: Transport.GRPC, options: { package: 'googlecloudstorage', - protoPath: 'src/proto/upload.proto', + protoPath: '../../protos/upload.proto', url: `${process.env.UPLOAD_MICROSERVICE_HOST || "0.0.0.0"}:${process.env.UPLOAD_SERVICE_PORT || 3003}`, }, }, diff --git a/server/k8s/gateway-autoscaler.yml b/server/k8s/gateway-autoscaler.yml new file mode 100644 index 00000000..f80edb44 --- /dev/null +++ b/server/k8s/gateway-autoscaler.yml @@ -0,0 +1,15 @@ +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: gateway-deployment + namespace: gateway + clusterName: klowhub-api-cluster +spec: + targetRef: + kind: Deployment + name: gateway-deployment + apiVersion: apps/v1 + updatePolicy: + updateMode: Auto + resourcePolicy: + containerPolicies: [] From 5e0a7b8902295ed007ffc4dbe0580e9dca362b1a Mon Sep 17 00:00:00 2001 From: Marcos Lopez Date: Sun, 24 Nov 2024 20:31:26 -0300 Subject: [PATCH 3/6] fix: add hpa yml files --- server/k8s/courses-deployment.yml | 7 +++++++ server/k8s/courses-hpa.yml | 19 +++++++++++++++++++ server/k8s/gateway-autoscaler.yml | 15 --------------- server/k8s/gateway-deployment.yml | 7 +++++++ server/k8s/gateway-hpa.yml | 19 +++++++++++++++++++ server/k8s/upload-deployment.yml | 7 +++++++ server/k8s/upload-hpa.yml | 19 +++++++++++++++++++ server/k8s/users-deployment.yml | 7 +++++++ server/k8s/users-hpa.yml | 19 +++++++++++++++++++ 9 files changed, 104 insertions(+), 15 deletions(-) create mode 100644 server/k8s/courses-hpa.yml delete mode 100644 server/k8s/gateway-autoscaler.yml create mode 100644 server/k8s/gateway-hpa.yml create mode 100644 server/k8s/upload-hpa.yml create mode 100644 server/k8s/users-hpa.yml diff --git a/server/k8s/courses-deployment.yml b/server/k8s/courses-deployment.yml index a002dfc8..b3fa4b37 100644 --- a/server/k8s/courses-deployment.yml +++ b/server/k8s/courses-deployment.yml @@ -21,6 +21,13 @@ spec: image: ${GCLOUD_REGION}-docker.pkg.dev/${GCLOUD_PROJECT_ID}/klowhub-server/${COURSE_SERVICE_NAME}:${IMAGE_TAG} ports: - containerPort: 3002 + resources: + requests: + cpu: "50m" + memory: "64Mi" + limits: + cpu: "100m" + memory: "128Mi" env: - name: NODE_ENV value: "production" diff --git a/server/k8s/courses-hpa.yml b/server/k8s/courses-hpa.yml new file mode 100644 index 00000000..3345781d --- /dev/null +++ b/server/k8s/courses-hpa.yml @@ -0,0 +1,19 @@ +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: courses-hpa + namespace: courseservice +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: courses-deployment + minReplicas: 1 + maxReplicas: 3 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 80 \ No newline at end of file diff --git a/server/k8s/gateway-autoscaler.yml b/server/k8s/gateway-autoscaler.yml deleted file mode 100644 index f80edb44..00000000 --- a/server/k8s/gateway-autoscaler.yml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: autoscaling.k8s.io/v1 -kind: VerticalPodAutoscaler -metadata: - name: gateway-deployment - namespace: gateway - clusterName: klowhub-api-cluster -spec: - targetRef: - kind: Deployment - name: gateway-deployment - apiVersion: apps/v1 - updatePolicy: - updateMode: Auto - resourcePolicy: - containerPolicies: [] diff --git a/server/k8s/gateway-deployment.yml b/server/k8s/gateway-deployment.yml index 891d9635..5fa40381 100644 --- a/server/k8s/gateway-deployment.yml +++ b/server/k8s/gateway-deployment.yml @@ -21,6 +21,13 @@ spec: image: ${GCLOUD_REGION}-docker.pkg.dev/${GCLOUD_PROJECT_ID}/klowhub-server/${GATEWAY_SERVICE_NAME}:${IMAGE_TAG} ports: - containerPort: 3000 + resources: + requests: + cpu: "50m" + memory: "64Mi" + limits: + cpu: "100m" + memory: "128Mi" env: - name: NODE_ENV value: "production" diff --git a/server/k8s/gateway-hpa.yml b/server/k8s/gateway-hpa.yml new file mode 100644 index 00000000..61170c5b --- /dev/null +++ b/server/k8s/gateway-hpa.yml @@ -0,0 +1,19 @@ +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: gateway-hpa + namespace: gateway +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: gateway-deployment + minReplicas: 1 + maxReplicas: 3 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 80 \ No newline at end of file diff --git a/server/k8s/upload-deployment.yml b/server/k8s/upload-deployment.yml index 9527832a..1928b167 100644 --- a/server/k8s/upload-deployment.yml +++ b/server/k8s/upload-deployment.yml @@ -21,6 +21,13 @@ spec: image: ${GCLOUD_REGION}-docker.pkg.dev/${GCLOUD_PROJECT_ID}/klowhub-server/${UPLOAD_SERVICE_NAME}:${IMAGE_TAG} ports: - containerPort: 3003 + resources: + requests: + cpu: "50m" + memory: "64Mi" + limits: + cpu: "100m" + memory: "128Mi" env: - name: NODE_ENV value: "production" diff --git a/server/k8s/upload-hpa.yml b/server/k8s/upload-hpa.yml new file mode 100644 index 00000000..73fda9b9 --- /dev/null +++ b/server/k8s/upload-hpa.yml @@ -0,0 +1,19 @@ +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: upload-hpa + namespace: gcc-upload +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: klowhub-upload-api-deployment + minReplicas: 1 + maxReplicas: 3 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 80 \ No newline at end of file diff --git a/server/k8s/users-deployment.yml b/server/k8s/users-deployment.yml index ea43f0a5..bf1d662d 100644 --- a/server/k8s/users-deployment.yml +++ b/server/k8s/users-deployment.yml @@ -21,6 +21,13 @@ spec: image: ${GCLOUD_REGION}-docker.pkg.dev/${GCLOUD_PROJECT_ID}/klowhub-server/${USERS_SERVICE_NAME}:${IMAGE_TAG} ports: - containerPort: 3001 + resources: + requests: + cpu: "50m" + memory: "64Mi" + limits: + cpu: "100m" + memory: "128Mi" env: - name: NODE_ENV value: "production" diff --git a/server/k8s/users-hpa.yml b/server/k8s/users-hpa.yml new file mode 100644 index 00000000..2a9138de --- /dev/null +++ b/server/k8s/users-hpa.yml @@ -0,0 +1,19 @@ +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: users-hpa + namespace: userservice +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: users-deployment + minReplicas: 1 + maxReplicas: 3 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 80 \ No newline at end of file From 6ad7211285e56a47be0f9754c02f778087fb17ae Mon Sep 17 00:00:00 2001 From: Marcos Lopez Date: Sun, 24 Nov 2024 20:40:34 -0300 Subject: [PATCH 4/6] fix: fixe upload service url and max replicas --- server/apps/gateway/src/pubsub/pubsub.module.ts | 2 +- server/k8s/courses-hpa.yml | 2 +- server/k8s/gateway-hpa.yml | 2 +- server/k8s/upload-hpa.yml | 2 +- server/k8s/users-hpa.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/server/apps/gateway/src/pubsub/pubsub.module.ts b/server/apps/gateway/src/pubsub/pubsub.module.ts index de14e49a..84117377 100644 --- a/server/apps/gateway/src/pubsub/pubsub.module.ts +++ b/server/apps/gateway/src/pubsub/pubsub.module.ts @@ -12,7 +12,7 @@ import { PubSubGatewayService } from './pubsub.gateway.service'; options: { package: 'googlecloudstorage', protoPath: '../../protos/upload.proto', - url: '0.0.0.0:50051', + url: `${process.env.UPLOAD_MICROSERVICE_HOST || "0.0.0.0"}:${process.env.UPLOAD_SERVICE_PORT || 3003}`, }, }, ]), diff --git a/server/k8s/courses-hpa.yml b/server/k8s/courses-hpa.yml index 3345781d..9705446f 100644 --- a/server/k8s/courses-hpa.yml +++ b/server/k8s/courses-hpa.yml @@ -9,7 +9,7 @@ spec: kind: Deployment name: courses-deployment minReplicas: 1 - maxReplicas: 3 + maxReplicas: 2 metrics: - type: Resource resource: diff --git a/server/k8s/gateway-hpa.yml b/server/k8s/gateway-hpa.yml index 61170c5b..4f2bf90c 100644 --- a/server/k8s/gateway-hpa.yml +++ b/server/k8s/gateway-hpa.yml @@ -9,7 +9,7 @@ spec: kind: Deployment name: gateway-deployment minReplicas: 1 - maxReplicas: 3 + maxReplicas: 2 metrics: - type: Resource resource: diff --git a/server/k8s/upload-hpa.yml b/server/k8s/upload-hpa.yml index 73fda9b9..f832d764 100644 --- a/server/k8s/upload-hpa.yml +++ b/server/k8s/upload-hpa.yml @@ -9,7 +9,7 @@ spec: kind: Deployment name: klowhub-upload-api-deployment minReplicas: 1 - maxReplicas: 3 + maxReplicas: 2 metrics: - type: Resource resource: diff --git a/server/k8s/users-hpa.yml b/server/k8s/users-hpa.yml index 2a9138de..234cadb8 100644 --- a/server/k8s/users-hpa.yml +++ b/server/k8s/users-hpa.yml @@ -9,7 +9,7 @@ spec: kind: Deployment name: users-deployment minReplicas: 1 - maxReplicas: 3 + maxReplicas: 2 metrics: - type: Resource resource: From 6ae6af6a046d3336bc3dddf69a3263b10a7d2307 Mon Sep 17 00:00:00 2001 From: Marcos Lopez Date: Sun, 24 Nov 2024 21:03:56 -0300 Subject: [PATCH 5/6] fix: fixe add join-path in proto paths --- server/apps/gateway/protos/upload.proto | 14 ++++++++- server/apps/gateway/src/gateway.module.ts | 3 +- server/apps/gateway/src/proto/upload.proto | 30 ------------------- .../apps/gateway/src/pubsub/pubsub.module.ts | 3 +- .../apps/gateway/src/upload/upload.module.ts | 3 +- 5 files changed, 19 insertions(+), 34 deletions(-) delete mode 100644 server/apps/gateway/src/proto/upload.proto diff --git a/server/apps/gateway/protos/upload.proto b/server/apps/gateway/protos/upload.proto index 2c6d61ba..a4748f17 100644 --- a/server/apps/gateway/protos/upload.proto +++ b/server/apps/gateway/protos/upload.proto @@ -1,7 +1,19 @@ syntax = "proto3"; -package googlecloudstorage; +package googlecloudstorage; // Este será el paquete común para ambos servicios +// Servicio PubSub +service PubSubService { + rpc Test (TestRequest) returns (TestResponse); +} + +message TestRequest {} + +message TestResponse { + string message = 1; +} + +// Servicio GoogleCloudStorage service GoogleCloudStorageService { rpc UploadFile (UploadFileRequest) returns (UploadFileResponse); } diff --git a/server/apps/gateway/src/gateway.module.ts b/server/apps/gateway/src/gateway.module.ts index 5dca70ca..89be967c 100644 --- a/server/apps/gateway/src/gateway.module.ts +++ b/server/apps/gateway/src/gateway.module.ts @@ -2,6 +2,7 @@ import { Module } from '@nestjs/common'; import { ClientsModule, Transport } from '@nestjs/microservices'; import { AuthController } from './auth/auth.controllers'; import { UploadController } from './upload/upload.controllers'; +import { join } from "path"; import * as dotenv from 'dotenv'; dotenv.config(); @@ -29,7 +30,7 @@ dotenv.config(); transport: Transport.GRPC, options: { package: 'googlecloudstorage', - protoPath: '../protos/upload.proto', + protoPath: join(__dirname,'../protos/upload.proto'), url: `${process.env.UPLOAD_MICROSERVICE_HOST || "0.0.0.0"}:${process.env.UPLOAD_SERVICE_PORT || 3003}`, }, }, diff --git a/server/apps/gateway/src/proto/upload.proto b/server/apps/gateway/src/proto/upload.proto deleted file mode 100644 index a4748f17..00000000 --- a/server/apps/gateway/src/proto/upload.proto +++ /dev/null @@ -1,30 +0,0 @@ -syntax = "proto3"; - -package googlecloudstorage; // Este será el paquete común para ambos servicios - -// Servicio PubSub -service PubSubService { - rpc Test (TestRequest) returns (TestResponse); -} - -message TestRequest {} - -message TestResponse { - string message = 1; -} - -// Servicio GoogleCloudStorage -service GoogleCloudStorageService { - rpc UploadFile (UploadFileRequest) returns (UploadFileResponse); -} - -message UploadFileRequest { - string filename = 1; - bytes file = 2; - string userId = 3; -} - -message UploadFileResponse { - string url = 1; - string message = 2; -} \ No newline at end of file diff --git a/server/apps/gateway/src/pubsub/pubsub.module.ts b/server/apps/gateway/src/pubsub/pubsub.module.ts index 84117377..b1ef8279 100644 --- a/server/apps/gateway/src/pubsub/pubsub.module.ts +++ b/server/apps/gateway/src/pubsub/pubsub.module.ts @@ -2,6 +2,7 @@ import { Module } from '@nestjs/common'; import { ClientsModule, Transport } from '@nestjs/microservices'; import { PubSubGatewayController } from './pubsub.gateway.controller'; import { PubSubGatewayService } from './pubsub.gateway.service'; +import { join } from "path"; @Module({ imports: [ @@ -11,7 +12,7 @@ import { PubSubGatewayService } from './pubsub.gateway.service'; transport: Transport.GRPC, options: { package: 'googlecloudstorage', - protoPath: '../../protos/upload.proto', + protoPath: join(__dirname,'../../protos/upload.proto'), url: `${process.env.UPLOAD_MICROSERVICE_HOST || "0.0.0.0"}:${process.env.UPLOAD_SERVICE_PORT || 3003}`, }, }, diff --git a/server/apps/gateway/src/upload/upload.module.ts b/server/apps/gateway/src/upload/upload.module.ts index aa3fce2b..9d464ecb 100644 --- a/server/apps/gateway/src/upload/upload.module.ts +++ b/server/apps/gateway/src/upload/upload.module.ts @@ -1,6 +1,7 @@ import { Module } from '@nestjs/common'; import { ClientsModule, Transport } from '@nestjs/microservices'; import { UploadController } from './upload.controllers'; +import { join } from "path"; @Module({ imports: [ @@ -10,7 +11,7 @@ import { UploadController } from './upload.controllers'; transport: Transport.GRPC, options: { package: 'googlecloudstorage', - protoPath: '../../protos/upload.proto', + protoPath: join(__dirname,'../../protos/upload.proto'), url: `${process.env.UPLOAD_MICROSERVICE_HOST || "0.0.0.0"}:${process.env.UPLOAD_SERVICE_PORT || 3003}`, }, }, From 4b42ed86f3a9b14156cf0264cadd10f1333104ac Mon Sep 17 00:00:00 2001 From: Marcos Lopez Date: Sun, 24 Nov 2024 21:24:34 -0300 Subject: [PATCH 6/6] fix: fixe gateway controller live check --- server/api/check-deploy.rest | 1 - server/api/check-gateway-deploy.rest | 3 +++ server/api/check-gateway-local.rest | 3 +++ server/apps/gateway/src/app.module.ts | 2 ++ server/apps/gateway/src/gateway.controller.ts | 2 +- server/apps/gateway/src/middleware/routersPublics.ts | 1 + 6 files changed, 10 insertions(+), 2 deletions(-) delete mode 100644 server/api/check-deploy.rest create mode 100644 server/api/check-gateway-deploy.rest create mode 100644 server/api/check-gateway-local.rest diff --git a/server/api/check-deploy.rest b/server/api/check-deploy.rest deleted file mode 100644 index bf23fa77..00000000 --- a/server/api/check-deploy.rest +++ /dev/null @@ -1 +0,0 @@ -GET http://34.111.85.215/gateway \ No newline at end of file diff --git a/server/api/check-gateway-deploy.rest b/server/api/check-gateway-deploy.rest new file mode 100644 index 00000000..7608154d --- /dev/null +++ b/server/api/check-gateway-deploy.rest @@ -0,0 +1,3 @@ +### Check Gateway Deploy +GET http://34.111.85.215/gateway/hello +Content-Type: application/json \ No newline at end of file diff --git a/server/api/check-gateway-local.rest b/server/api/check-gateway-local.rest new file mode 100644 index 00000000..0052a031 --- /dev/null +++ b/server/api/check-gateway-local.rest @@ -0,0 +1,3 @@ +### Check Gateway Local +GET http://localhost:3000/gateway/hello +Content-Type: application/json \ No newline at end of file diff --git a/server/apps/gateway/src/app.module.ts b/server/apps/gateway/src/app.module.ts index bf0d70f6..0c0d6f5d 100644 --- a/server/apps/gateway/src/app.module.ts +++ b/server/apps/gateway/src/app.module.ts @@ -3,7 +3,9 @@ import { AuthModule } from './auth/auth.module'; import { UploadModule } from './upload/upload.module'; import { CoursesModule } from './courses/courses.module'; import { PubSubModule } from './pubsub/pubsub.module'; +import { GatewayController } from './gateway.controller'; @Module({ imports: [AuthModule, UploadModule, CoursesModule,PubSubModule], + controllers: [GatewayController], }) export class AppModule {} diff --git a/server/apps/gateway/src/gateway.controller.ts b/server/apps/gateway/src/gateway.controller.ts index 00893c2a..17c41206 100644 --- a/server/apps/gateway/src/gateway.controller.ts +++ b/server/apps/gateway/src/gateway.controller.ts @@ -2,7 +2,7 @@ import { Controller, Get } from '@nestjs/common'; @Controller('gateway') export class GatewayController { - @Get() + @Get("/hello") getHello(): string { return 'Hello from Gateway!'; } diff --git a/server/apps/gateway/src/middleware/routersPublics.ts b/server/apps/gateway/src/middleware/routersPublics.ts index 629f6373..5745cae5 100644 --- a/server/apps/gateway/src/middleware/routersPublics.ts +++ b/server/apps/gateway/src/middleware/routersPublics.ts @@ -3,4 +3,5 @@ export const publicRoutes: string[] = [ '/auth/login', '/auth/verifyEmail', '/auth/resetToken', + '/gateway/hello' ];