From 62bf25009c14dd905d535d4465ff3e9e2dc7126b Mon Sep 17 00:00:00 2001 From: Peter Hanssens Date: Sat, 15 Mar 2025 00:26:15 +1100 Subject: [PATCH 01/25] adding ECR builds --- .circleci/config.yml | 158 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 140 insertions(+), 18 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 88a98ff9..f56ce847 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -9,20 +9,23 @@ parameters: aws-region: type: string default: "us-east-1" - ecr-repository: + ecr-repository-prefix: type: string - default: "transformers-mage" + default: "synthetix-data/indexer" ecs-cluster: type: string default: "synthetix-data" - ecs-service: + deploy-target: type: string - default: "transformers-mage-service" + default: "eks" # Can be "ecs" or "eks" jobs: - build-and-push: + build-and-push-images: docker: - - image: cimg/python:3.10 + - image: cimg/base:2023.03 + parameters: + network: + type: string steps: - checkout - setup_remote_docker: @@ -33,20 +36,26 @@ jobs: role-arn: ${AWS_ROLE_ARN} aws-region: << pipeline.parameters.aws-region >> - # Build and push Docker image + # Build and push Docker image for specific network - aws-ecr/build-and-push-image: aws-access-key-id: ${AWS_ACCESS_KEY_ID} aws-secret-access-key: ${AWS_SECRET_ACCESS_KEY} account-url: ${AWS_ECR_ACCOUNT_URL} - repo: << pipeline.parameters.ecr-repository >> + repo: << pipeline.parameters.ecr-repository-prefix >> region: << pipeline.parameters.aws-region >> - tag: "${CIRCLE_SHA1},latest" - path: ./transformers-mage - dockerfile: ./transformers-mage/Dockerfile + tag: "${CIRCLE_SHA1}-<< parameters.network >>,latest-<< parameters.network >>" + path: ./indexers/<< parameters.network >> + dockerfile: ./indexers/<< parameters.network >>/Dockerfile deploy-to-ecs: docker: - image: cimg/python:3.10 + parameters: + network: + type: string + service-name: + type: string + default: "indexer-<< parameters.network >>" steps: - checkout - aws-cli/setup: @@ -58,7 +67,7 @@ jobs: name: Fetch current task definition command: | aws ecs describe-task-definition \ - --task-definition << pipeline.parameters.ecs-service >> \ + --task-definition << parameters.service-name >> \ --region << pipeline.parameters.aws-region >> \ --output json > task-definition.json @@ -69,7 +78,7 @@ jobs: jq '.taskDefinition.containerDefinitions' task-definition.json > container-defs.json # Update the image in the container definitions - jq --arg IMAGE "${AWS_ECR_ACCOUNT_URL}/<< pipeline.parameters.ecr-repository >>:${CIRCLE_SHA1}" \ + jq --arg IMAGE "${AWS_ECR_ACCOUNT_URL}/<< pipeline.parameters.ecr-repository-prefix >>:${CIRCLE_SHA1}-<< parameters.network >>" \ '.[0].image = $IMAGE' container-defs.json > updated-container-defs.json # Get other task definition parameters @@ -97,26 +106,139 @@ jobs: # Update the ECS service with the new task definition - aws-ecs/update-service: - family: << pipeline.parameters.ecs-service >> + family: << parameters.service-name >> cluster-name: << pipeline.parameters.ecs-cluster >> - container-image-name-updates: "container=transformers-mage,tag=${CIRCLE_SHA1}" + container-image-name-updates: "container=indexer,tag=${CIRCLE_SHA1}-<< parameters.network >>" verify-revision-is-deployed: true max-poll-attempts: 20 poll-interval: 20 + deploy-to-eks: + docker: + - image: cimg/python:3.10 + parameters: + network: + type: string + steps: + - checkout + - aws-cli/setup: + role-arn: ${AWS_ROLE_ARN} + aws-region: << pipeline.parameters.aws-region >> + + - run: + name: Install kubectl + command: | + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" + chmod +x kubectl + sudo mv kubectl /usr/local/bin/ + + - run: + name: Configure kubectl + command: | + aws eks update-kubeconfig --name ${EKS_CLUSTER_NAME} --region << pipeline.parameters.aws-region >> + + - run: + name: Update deployment + command: | + # Create a patch to update the image + cat > patch.yaml <>:${CIRCLE_SHA1}-<< parameters.network >> + EOL + + # Apply the patch to the deployment + kubectl patch deployment indexer-<< parameters.network >> --patch "$(cat patch.yaml)" + + # Wait for rollout to complete + kubectl rollout status deployment/indexer-<< parameters.network >> --timeout=300s + workflows: version: 2 build-deploy: jobs: - - build-and-push: + # Build and push images for all networks + - build-and-push-images: context: aws-credentials + matrix: + parameters: + network: [ + "arbitrum-mainnet", + "arbitrum-sepolia", + "base-mainnet", + "base-mainnet-lt", + "base-sepolia", + "eth-mainnet", + "optimism-mainnet", + "optimism-mainnet-tlx", + "snax-mainnet", + "snax-testnet" + ] filters: branches: only: main + + # Deploy to ECS if target is ECS - deploy-to-ecs: context: aws-credentials + matrix: + parameters: + network: [ + "arbitrum-mainnet", + "arbitrum-sepolia", + "base-mainnet", + "base-mainnet-lt", + "base-sepolia", + "eth-mainnet", + "optimism-mainnet", + "optimism-mainnet-tlx", + "snax-mainnet", + "snax-testnet" + ] + service-name: [ + "indexer-arbitrum-mainnet", + "indexer-arbitrum-sepolia", + "indexer-base-mainnet", + "indexer-base-mainnet-lt", + "indexer-base-sepolia", + "indexer-eth-mainnet", + "indexer-optimism-mainnet", + "indexer-optimism-mainnet-tlx", + "indexer-snax-mainnet", + "indexer-snax-testnet" + ] requires: - - build-and-push + - build-and-push-images filters: branches: - only: main \ No newline at end of file + only: main + when: + equal: [ "ecs", << pipeline.parameters.deploy-target >> ] + + # Deploy to EKS if target is EKS + - deploy-to-eks: + context: aws-credentials + matrix: + parameters: + network: [ + "arbitrum-mainnet", + "arbitrum-sepolia", + "base-mainnet", + "base-mainnet-lt", + "base-sepolia", + "eth-mainnet", + "optimism-mainnet", + "optimism-mainnet-tlx", + "snax-mainnet", + "snax-testnet" + ] + requires: + - build-and-push-images + filters: + branches: + only: main + when: + equal: [ "eks", << pipeline.parameters.deploy-target >> ] \ No newline at end of file From dcfdfcfb694067b1aef8c59d97d7245f26d7d7ad Mon Sep 17 00:00:00 2001 From: Peter Hanssens Date: Sat, 15 Mar 2025 00:44:24 +1100 Subject: [PATCH 02/25] init --- .circleci/config.yml | 255 +++++++++------------- .gitignore | 1 + k8s/configmap.yaml | 22 ++ k8s/deployment-template.yaml | 97 ++++++++ k8s/deployments/arbitrum-mainnet.yaml | 97 ++++++++ k8s/deployments/arbitrum-sepolia.yaml | 97 ++++++++ k8s/deployments/base-mainnet-lt.yaml | 97 ++++++++ k8s/deployments/base-mainnet.yaml | 97 ++++++++ k8s/deployments/base-sepolia.yaml | 97 ++++++++ k8s/deployments/eth-mainnet.yaml | 97 ++++++++ k8s/deployments/optimism-mainnet-tlx.yaml | 97 ++++++++ k8s/deployments/optimism-mainnet.yaml | 97 ++++++++ k8s/deployments/snax-mainnet.yaml | 97 ++++++++ k8s/deployments/snax-testnet.yaml | 97 ++++++++ k8s/external-secrets.yaml | 30 +++ scripts/generate-deployments.sh | 136 ++++++++++++ 16 files changed, 1365 insertions(+), 146 deletions(-) create mode 100644 k8s/configmap.yaml create mode 100644 k8s/deployment-template.yaml create mode 100644 k8s/deployments/arbitrum-mainnet.yaml create mode 100644 k8s/deployments/arbitrum-sepolia.yaml create mode 100644 k8s/deployments/base-mainnet-lt.yaml create mode 100644 k8s/deployments/base-mainnet.yaml create mode 100644 k8s/deployments/base-sepolia.yaml create mode 100644 k8s/deployments/eth-mainnet.yaml create mode 100644 k8s/deployments/optimism-mainnet-tlx.yaml create mode 100644 k8s/deployments/optimism-mainnet.yaml create mode 100644 k8s/deployments/snax-mainnet.yaml create mode 100644 k8s/deployments/snax-testnet.yaml create mode 100644 k8s/external-secrets.yaml create mode 100755 scripts/generate-deployments.sh diff --git a/.circleci/config.yml b/.circleci/config.yml index f56ce847..d64435a1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,7 +3,8 @@ version: 2.1 orbs: aws-cli: circleci/aws-cli@3.1 aws-ecr: circleci/aws-ecr@8.2.1 - aws-ecs: circleci/aws-ecs@3.2.0 + aws-eks: circleci/aws-eks@2.2.0 + kubernetes: circleci/kubernetes@1.3 parameters: aws-region: @@ -12,12 +13,9 @@ parameters: ecr-repository-prefix: type: string default: "synthetix-data/indexer" - ecs-cluster: + eks-cluster-name: type: string - default: "synthetix-data" - deploy-target: - type: string - default: "eks" # Can be "ecs" or "eks" + default: "synthetix-eks-cluster" jobs: build-and-push-images: @@ -47,114 +45,131 @@ jobs: path: ./indexers/<< parameters.network >> dockerfile: ./indexers/<< parameters.network >>/Dockerfile - deploy-to-ecs: + deploy-to-eks: docker: - image: cimg/python:3.10 - parameters: - network: - type: string - service-name: - type: string - default: "indexer-<< parameters.network >>" steps: - checkout - aws-cli/setup: role-arn: ${AWS_ROLE_ARN} aws-region: << pipeline.parameters.aws-region >> - # Update ECS task definition with new image - - run: - name: Fetch current task definition - command: | - aws ecs describe-task-definition \ - --task-definition << parameters.service-name >> \ - --region << pipeline.parameters.aws-region >> \ - --output json > task-definition.json - - - run: - name: Update task definition with new image - command: | - # Extract the container definitions - jq '.taskDefinition.containerDefinitions' task-definition.json > container-defs.json - - # Update the image in the container definitions - jq --arg IMAGE "${AWS_ECR_ACCOUNT_URL}/<< pipeline.parameters.ecr-repository-prefix >>:${CIRCLE_SHA1}-<< parameters.network >>" \ - '.[0].image = $IMAGE' container-defs.json > updated-container-defs.json - - # Get other task definition parameters - FAMILY=$(jq -r '.taskDefinition.family' task-definition.json) - EXECUTION_ROLE=$(jq -r '.taskDefinition.executionRoleArn' task-definition.json) - TASK_ROLE=$(jq -r '.taskDefinition.taskRoleArn' task-definition.json) - NETWORK_MODE=$(jq -r '.taskDefinition.networkMode' task-definition.json) - VOLUMES=$(jq '.taskDefinition.volumes' task-definition.json) - PLACEMENT_CONSTRAINTS=$(jq '.taskDefinition.placementConstraints' task-definition.json) - - # Register new task definition - aws ecs register-task-definition \ - --family $FAMILY \ - --execution-role-arn $EXECUTION_ROLE \ - --task-role-arn $TASK_ROLE \ - --network-mode $NETWORK_MODE \ - --container-definitions file://updated-container-defs.json \ - --volumes "$VOLUMES" \ - --placement-constraints "$PLACEMENT_CONSTRAINTS" \ - --region << pipeline.parameters.aws-region >> \ - --output json > new-task-definition.json - - # Store the new task definition ARN for the next step - echo "export NEW_TASK_DEFINITION_ARN=$(jq -r '.taskDefinition.taskDefinitionArn' new-task-definition.json)" >> $BASH_ENV + - kubernetes/install-kubectl - # Update the ECS service with the new task definition - - aws-ecs/update-service: - family: << parameters.service-name >> - cluster-name: << pipeline.parameters.ecs-cluster >> - container-image-name-updates: "container=indexer,tag=${CIRCLE_SHA1}-<< parameters.network >>" - verify-revision-is-deployed: true - max-poll-attempts: 20 - poll-interval: 20 - - deploy-to-eks: - docker: - - image: cimg/python:3.10 - parameters: - network: - type: string - steps: - - checkout - - aws-cli/setup: - role-arn: ${AWS_ROLE_ARN} + - aws-eks/update-kubeconfig-with-authenticator: + cluster-name: << pipeline.parameters.eks-cluster-name >> aws-region: << pipeline.parameters.aws-region >> + # Get Aurora DB endpoint from CloudFormation outputs - run: - name: Install kubectl + name: Get Aurora DB details command: | - curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" - chmod +x kubectl - sudo mv kubectl /usr/local/bin/ + # Get DB endpoint from CloudFormation output + DB_ENDPOINT=$(aws cloudformation describe-stacks --stack-name synthetix-aurora-stack --query "Stacks[0].Outputs[?OutputKey=='DBEndpoint'].OutputValue" --output text) + echo "DB_ENDPOINT=$DB_ENDPOINT" >> $BASH_ENV + + # Get DB secret ARN + DB_SECRET_ARN=$(aws cloudformation describe-stacks --stack-name synthetix-aurora-stack --query "Stacks[0].Outputs[?OutputKey=='DBSecretArn'].OutputValue" --output text) + echo "DB_SECRET_ARN=$DB_SECRET_ARN" >> $BASH_ENV + # Update ConfigMap with Aurora DB endpoint - run: - name: Configure kubectl + name: Update ConfigMap with Aurora DB endpoint command: | - aws eks update-kubeconfig --name ${EKS_CLUSTER_NAME} --region << pipeline.parameters.aws-region >> + # Create namespace if it doesn't exist + if ! kubectl get namespace synthetix-data > /dev/null 2>&1; then + kubectl create namespace synthetix-data + fi + + # Create or update ConfigMap + cat > db-config.yaml < patch.yaml < external-secret.yaml <>:${CIRCLE_SHA1}-<< parameters.network >> - EOL + refreshInterval: "15m" + secretStoreRef: + name: aws-secretsmanager + kind: ClusterSecretStore + target: + name: aurora-db-credentials + creationPolicy: Owner + data: + - secretKey: password + remoteRef: + key: "$(basename $DB_SECRET_ARN)" + property: password + - secretKey: username + remoteRef: + key: "$(basename $DB_SECRET_ARN)" + property: username + - secretKey: conduit-api-key + remoteRef: + key: "synthetix-conduit-api-key" + property: key + EOF - # Apply the patch to the deployment - kubectl patch deployment indexer-<< parameters.network >> --patch "$(cat patch.yaml)" + kubectl apply -f external-secret.yaml + + # Apply all deployments + - run: + name: Deploy all indexers + command: | + # Replace IMAGE_TAG in all deployment files + for deployment in k8s/deployments/*.yaml; do + network=$(basename $deployment .yaml) + image_tag="${AWS_ECR_ACCOUNT_URL}/${pipeline.parameters.ecr-repository-prefix}:${CIRCLE_SHA1}-${network}" + + # Replace image tag in deployment file + sed -i "s|\${AWS_ACCOUNT_ID}.dkr.ecr.\${AWS_REGION}.amazonaws.com/synthetix-data/indexer:latest-${network}|$image_tag|g" $deployment + + # Apply deployment + kubectl apply -f $deployment + + echo "Deployed $network" + done - # Wait for rollout to complete - kubectl rollout status deployment/indexer-<< parameters.network >> --timeout=300s + # Wait for deployments to be ready + for network in arbitrum-mainnet arbitrum-sepolia base-mainnet base-mainnet-lt base-sepolia eth-mainnet optimism-mainnet optimism-mainnet-tlx snax-mainnet snax-testnet; do + kubectl rollout status deployment/indexer-$network -n synthetix-data --timeout=300s + done workflows: version: 2 @@ -181,64 +196,12 @@ workflows: branches: only: main - # Deploy to ECS if target is ECS - - deploy-to-ecs: - context: aws-credentials - matrix: - parameters: - network: [ - "arbitrum-mainnet", - "arbitrum-sepolia", - "base-mainnet", - "base-mainnet-lt", - "base-sepolia", - "eth-mainnet", - "optimism-mainnet", - "optimism-mainnet-tlx", - "snax-mainnet", - "snax-testnet" - ] - service-name: [ - "indexer-arbitrum-mainnet", - "indexer-arbitrum-sepolia", - "indexer-base-mainnet", - "indexer-base-mainnet-lt", - "indexer-base-sepolia", - "indexer-eth-mainnet", - "indexer-optimism-mainnet", - "indexer-optimism-mainnet-tlx", - "indexer-snax-mainnet", - "indexer-snax-testnet" - ] - requires: - - build-and-push-images - filters: - branches: - only: main - when: - equal: [ "ecs", << pipeline.parameters.deploy-target >> ] - - # Deploy to EKS if target is EKS + # Deploy to EKS with Aurora integration - deploy-to-eks: context: aws-credentials - matrix: - parameters: - network: [ - "arbitrum-mainnet", - "arbitrum-sepolia", - "base-mainnet", - "base-mainnet-lt", - "base-sepolia", - "eth-mainnet", - "optimism-mainnet", - "optimism-mainnet-tlx", - "snax-mainnet", - "snax-testnet" - ] requires: - build-and-push-images filters: branches: only: main - when: - equal: [ "eks", << pipeline.parameters.deploy-target >> ] \ No newline at end of file + \ No newline at end of file diff --git a/.gitignore b/.gitignore index 8d016ac0..bb287801 100644 --- a/.gitignore +++ b/.gitignore @@ -170,6 +170,7 @@ pnpm-lock.yaml lib builds deployments +!k8s/deployments logs # local data diff --git a/k8s/configmap.yaml b/k8s/configmap.yaml new file mode 100644 index 00000000..300766c5 --- /dev/null +++ b/k8s/configmap.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: db-config + namespace: synthetix-data +data: + # Aurora DB connection info - replace with actual values from your stack outputs + db-host: "synthetix-prod-postgres-cluster.cluster-xxxxxxxxxxxx.us-east-1.rds.amazonaws.com" + db-port: "5432" + + # Network RPC endpoints + arbitrum-mainnet-rpc: "https://arb1.arbitrum.io/rpc" + arbitrum-sepolia-rpc: "https://sepolia-rollup.arbitrum.io/rpc" + base-mainnet-rpc: "https://mainnet.base.org" + base-mainnet-lt-rpc: "https://mainnet.base.org" + base-sepolia-rpc: "https://sepolia.base.org" + eth-mainnet-rpc: "https://eth-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}" + optimism-mainnet-rpc: "https://mainnet.optimism.io" + optimism-mainnet-tlx-rpc: "https://mainnet.optimism.io" + snax-mainnet-rpc: "https://mainnet.snaxchain.io/" + snax-testnet-rpc: "https://testnet.snaxchain.io/" + \ No newline at end of file diff --git a/k8s/deployment-template.yaml b/k8s/deployment-template.yaml new file mode 100644 index 00000000..921e7f00 --- /dev/null +++ b/k8s/deployment-template.yaml @@ -0,0 +1,97 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: indexer-NETWORK_NAME + namespace: synthetix-data + labels: + app: synthetix-indexer + network: NETWORK_NAME +spec: + replicas: 1 + selector: + matchLabels: + app: synthetix-indexer + network: NETWORK_NAME + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 1 + maxUnavailable: 0 + template: + metadata: + labels: + app: synthetix-indexer + network: NETWORK_NAME + spec: + containers: + - name: indexer + image: ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/synthetix-data/indexer:latest-NETWORK_NAME + imagePullPolicy: Always + resources: + limits: + cpu: "1" + memory: "2Gi" + requests: + cpu: "500m" + memory: "1Gi" + ports: + - containerPort: 4350 + name: gql + env: + - name: DB_HOST + valueFrom: + configMapKeyRef: + name: db-config + key: db-host + - name: DB_PORT + valueFrom: + configMapKeyRef: + name: db-config + key: db-port + - name: DB_NAME + value: "DB_NAME_VALUE" + - name: DB_PASS + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: password + - name: DB_USER + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: username + - name: GQL_PORT + value: "4350" + - name: RPC_ENDPOINT + valueFrom: + configMapKeyRef: + name: db-config + key: NETWORK_NAME-rpc + - name: API_KEY + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: conduit-api-key + readinessProbe: + httpGet: + path: /health + port: 4350 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /health + port: 4350 + initialDelaySeconds: 60 + periodSeconds: 20 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + securityContext: + runAsNonRoot: true + runAsUser: 1000 + fsGroup: 1000 + terminationGracePeriodSeconds: 60 diff --git a/k8s/deployments/arbitrum-mainnet.yaml b/k8s/deployments/arbitrum-mainnet.yaml new file mode 100644 index 00000000..56acac04 --- /dev/null +++ b/k8s/deployments/arbitrum-mainnet.yaml @@ -0,0 +1,97 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: indexer-arbitrum-mainnet + namespace: synthetix-data + labels: + app: synthetix-indexer + network: arbitrum-mainnet +spec: + replicas: 1 + selector: + matchLabels: + app: synthetix-indexer + network: arbitrum-mainnet + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 1 + maxUnavailable: 0 + template: + metadata: + labels: + app: synthetix-indexer + network: arbitrum-mainnet + spec: + containers: + - name: indexer + image: ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/synthetix-data/indexer:latest-arbitrum-mainnet + imagePullPolicy: Always + resources: + limits: + cpu: "1" + memory: "2Gi" + requests: + cpu: "500m" + memory: "1Gi" + ports: + - containerPort: 4350 + name: gql + env: + - name: DB_HOST + valueFrom: + configMapKeyRef: + name: db-config + key: db-host + - name: DB_PORT + valueFrom: + configMapKeyRef: + name: db-config + key: db-port + - name: DB_NAME + value: "arbitrum_mainnet" + - name: DB_PASS + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: password + - name: DB_USER + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: username + - name: GQL_PORT + value: "4350" + - name: RPC_ENDPOINT + valueFrom: + configMapKeyRef: + name: db-config + key: arbitrum-mainnet-rpc + - name: API_KEY + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: conduit-api-key + readinessProbe: + httpGet: + path: /health + port: 4350 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /health + port: 4350 + initialDelaySeconds: 60 + periodSeconds: 20 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + securityContext: + runAsNonRoot: true + runAsUser: 1000 + fsGroup: 1000 + terminationGracePeriodSeconds: 60 diff --git a/k8s/deployments/arbitrum-sepolia.yaml b/k8s/deployments/arbitrum-sepolia.yaml new file mode 100644 index 00000000..ad1715df --- /dev/null +++ b/k8s/deployments/arbitrum-sepolia.yaml @@ -0,0 +1,97 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: indexer-arbitrum-sepolia + namespace: synthetix-data + labels: + app: synthetix-indexer + network: arbitrum-sepolia +spec: + replicas: 1 + selector: + matchLabels: + app: synthetix-indexer + network: arbitrum-sepolia + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 1 + maxUnavailable: 0 + template: + metadata: + labels: + app: synthetix-indexer + network: arbitrum-sepolia + spec: + containers: + - name: indexer + image: ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/synthetix-data/indexer:latest-arbitrum-sepolia + imagePullPolicy: Always + resources: + limits: + cpu: "1" + memory: "2Gi" + requests: + cpu: "500m" + memory: "1Gi" + ports: + - containerPort: 4350 + name: gql + env: + - name: DB_HOST + valueFrom: + configMapKeyRef: + name: db-config + key: db-host + - name: DB_PORT + valueFrom: + configMapKeyRef: + name: db-config + key: db-port + - name: DB_NAME + value: "arbitrum_sepolia" + - name: DB_PASS + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: password + - name: DB_USER + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: username + - name: GQL_PORT + value: "4350" + - name: RPC_ENDPOINT + valueFrom: + configMapKeyRef: + name: db-config + key: arbitrum-sepolia-rpc + - name: API_KEY + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: conduit-api-key + readinessProbe: + httpGet: + path: /health + port: 4350 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /health + port: 4350 + initialDelaySeconds: 60 + periodSeconds: 20 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + securityContext: + runAsNonRoot: true + runAsUser: 1000 + fsGroup: 1000 + terminationGracePeriodSeconds: 60 diff --git a/k8s/deployments/base-mainnet-lt.yaml b/k8s/deployments/base-mainnet-lt.yaml new file mode 100644 index 00000000..78e83579 --- /dev/null +++ b/k8s/deployments/base-mainnet-lt.yaml @@ -0,0 +1,97 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: indexer-base-mainnet-lt + namespace: synthetix-data + labels: + app: synthetix-indexer + network: base-mainnet-lt +spec: + replicas: 1 + selector: + matchLabels: + app: synthetix-indexer + network: base-mainnet-lt + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 1 + maxUnavailable: 0 + template: + metadata: + labels: + app: synthetix-indexer + network: base-mainnet-lt + spec: + containers: + - name: indexer + image: ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/synthetix-data/indexer:latest-base-mainnet-lt + imagePullPolicy: Always + resources: + limits: + cpu: "1" + memory: "2Gi" + requests: + cpu: "500m" + memory: "1Gi" + ports: + - containerPort: 4350 + name: gql + env: + - name: DB_HOST + valueFrom: + configMapKeyRef: + name: db-config + key: db-host + - name: DB_PORT + valueFrom: + configMapKeyRef: + name: db-config + key: db-port + - name: DB_NAME + value: "base_mainnet_lt" + - name: DB_PASS + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: password + - name: DB_USER + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: username + - name: GQL_PORT + value: "4350" + - name: RPC_ENDPOINT + valueFrom: + configMapKeyRef: + name: db-config + key: base-mainnet-lt-rpc + - name: API_KEY + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: conduit-api-key + readinessProbe: + httpGet: + path: /health + port: 4350 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /health + port: 4350 + initialDelaySeconds: 60 + periodSeconds: 20 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + securityContext: + runAsNonRoot: true + runAsUser: 1000 + fsGroup: 1000 + terminationGracePeriodSeconds: 60 diff --git a/k8s/deployments/base-mainnet.yaml b/k8s/deployments/base-mainnet.yaml new file mode 100644 index 00000000..928bdb52 --- /dev/null +++ b/k8s/deployments/base-mainnet.yaml @@ -0,0 +1,97 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: indexer-base-mainnet + namespace: synthetix-data + labels: + app: synthetix-indexer + network: base-mainnet +spec: + replicas: 1 + selector: + matchLabels: + app: synthetix-indexer + network: base-mainnet + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 1 + maxUnavailable: 0 + template: + metadata: + labels: + app: synthetix-indexer + network: base-mainnet + spec: + containers: + - name: indexer + image: ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/synthetix-data/indexer:latest-base-mainnet + imagePullPolicy: Always + resources: + limits: + cpu: "1" + memory: "2Gi" + requests: + cpu: "500m" + memory: "1Gi" + ports: + - containerPort: 4350 + name: gql + env: + - name: DB_HOST + valueFrom: + configMapKeyRef: + name: db-config + key: db-host + - name: DB_PORT + valueFrom: + configMapKeyRef: + name: db-config + key: db-port + - name: DB_NAME + value: "base_mainnet" + - name: DB_PASS + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: password + - name: DB_USER + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: username + - name: GQL_PORT + value: "4350" + - name: RPC_ENDPOINT + valueFrom: + configMapKeyRef: + name: db-config + key: base-mainnet-rpc + - name: API_KEY + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: conduit-api-key + readinessProbe: + httpGet: + path: /health + port: 4350 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /health + port: 4350 + initialDelaySeconds: 60 + periodSeconds: 20 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + securityContext: + runAsNonRoot: true + runAsUser: 1000 + fsGroup: 1000 + terminationGracePeriodSeconds: 60 diff --git a/k8s/deployments/base-sepolia.yaml b/k8s/deployments/base-sepolia.yaml new file mode 100644 index 00000000..d37c3f09 --- /dev/null +++ b/k8s/deployments/base-sepolia.yaml @@ -0,0 +1,97 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: indexer-base-sepolia + namespace: synthetix-data + labels: + app: synthetix-indexer + network: base-sepolia +spec: + replicas: 1 + selector: + matchLabels: + app: synthetix-indexer + network: base-sepolia + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 1 + maxUnavailable: 0 + template: + metadata: + labels: + app: synthetix-indexer + network: base-sepolia + spec: + containers: + - name: indexer + image: ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/synthetix-data/indexer:latest-base-sepolia + imagePullPolicy: Always + resources: + limits: + cpu: "1" + memory: "2Gi" + requests: + cpu: "500m" + memory: "1Gi" + ports: + - containerPort: 4350 + name: gql + env: + - name: DB_HOST + valueFrom: + configMapKeyRef: + name: db-config + key: db-host + - name: DB_PORT + valueFrom: + configMapKeyRef: + name: db-config + key: db-port + - name: DB_NAME + value: "base_sepolia" + - name: DB_PASS + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: password + - name: DB_USER + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: username + - name: GQL_PORT + value: "4350" + - name: RPC_ENDPOINT + valueFrom: + configMapKeyRef: + name: db-config + key: base-sepolia-rpc + - name: API_KEY + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: conduit-api-key + readinessProbe: + httpGet: + path: /health + port: 4350 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /health + port: 4350 + initialDelaySeconds: 60 + periodSeconds: 20 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + securityContext: + runAsNonRoot: true + runAsUser: 1000 + fsGroup: 1000 + terminationGracePeriodSeconds: 60 diff --git a/k8s/deployments/eth-mainnet.yaml b/k8s/deployments/eth-mainnet.yaml new file mode 100644 index 00000000..1b3c99f5 --- /dev/null +++ b/k8s/deployments/eth-mainnet.yaml @@ -0,0 +1,97 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: indexer-eth-mainnet + namespace: synthetix-data + labels: + app: synthetix-indexer + network: eth-mainnet +spec: + replicas: 1 + selector: + matchLabels: + app: synthetix-indexer + network: eth-mainnet + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 1 + maxUnavailable: 0 + template: + metadata: + labels: + app: synthetix-indexer + network: eth-mainnet + spec: + containers: + - name: indexer + image: ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/synthetix-data/indexer:latest-eth-mainnet + imagePullPolicy: Always + resources: + limits: + cpu: "1" + memory: "2Gi" + requests: + cpu: "500m" + memory: "1Gi" + ports: + - containerPort: 4350 + name: gql + env: + - name: DB_HOST + valueFrom: + configMapKeyRef: + name: db-config + key: db-host + - name: DB_PORT + valueFrom: + configMapKeyRef: + name: db-config + key: db-port + - name: DB_NAME + value: "eth_mainnet" + - name: DB_PASS + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: password + - name: DB_USER + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: username + - name: GQL_PORT + value: "4350" + - name: RPC_ENDPOINT + valueFrom: + configMapKeyRef: + name: db-config + key: eth-mainnet-rpc + - name: API_KEY + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: conduit-api-key + readinessProbe: + httpGet: + path: /health + port: 4350 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /health + port: 4350 + initialDelaySeconds: 60 + periodSeconds: 20 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + securityContext: + runAsNonRoot: true + runAsUser: 1000 + fsGroup: 1000 + terminationGracePeriodSeconds: 60 diff --git a/k8s/deployments/optimism-mainnet-tlx.yaml b/k8s/deployments/optimism-mainnet-tlx.yaml new file mode 100644 index 00000000..d8f6d1f0 --- /dev/null +++ b/k8s/deployments/optimism-mainnet-tlx.yaml @@ -0,0 +1,97 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: indexer-optimism-mainnet-tlx + namespace: synthetix-data + labels: + app: synthetix-indexer + network: optimism-mainnet-tlx +spec: + replicas: 1 + selector: + matchLabels: + app: synthetix-indexer + network: optimism-mainnet-tlx + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 1 + maxUnavailable: 0 + template: + metadata: + labels: + app: synthetix-indexer + network: optimism-mainnet-tlx + spec: + containers: + - name: indexer + image: ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/synthetix-data/indexer:latest-optimism-mainnet-tlx + imagePullPolicy: Always + resources: + limits: + cpu: "1" + memory: "2Gi" + requests: + cpu: "500m" + memory: "1Gi" + ports: + - containerPort: 4350 + name: gql + env: + - name: DB_HOST + valueFrom: + configMapKeyRef: + name: db-config + key: db-host + - name: DB_PORT + valueFrom: + configMapKeyRef: + name: db-config + key: db-port + - name: DB_NAME + value: "optimism_mainnet_tlx" + - name: DB_PASS + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: password + - name: DB_USER + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: username + - name: GQL_PORT + value: "4350" + - name: RPC_ENDPOINT + valueFrom: + configMapKeyRef: + name: db-config + key: optimism-mainnet-tlx-rpc + - name: API_KEY + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: conduit-api-key + readinessProbe: + httpGet: + path: /health + port: 4350 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /health + port: 4350 + initialDelaySeconds: 60 + periodSeconds: 20 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + securityContext: + runAsNonRoot: true + runAsUser: 1000 + fsGroup: 1000 + terminationGracePeriodSeconds: 60 diff --git a/k8s/deployments/optimism-mainnet.yaml b/k8s/deployments/optimism-mainnet.yaml new file mode 100644 index 00000000..fa781f12 --- /dev/null +++ b/k8s/deployments/optimism-mainnet.yaml @@ -0,0 +1,97 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: indexer-optimism-mainnet + namespace: synthetix-data + labels: + app: synthetix-indexer + network: optimism-mainnet +spec: + replicas: 1 + selector: + matchLabels: + app: synthetix-indexer + network: optimism-mainnet + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 1 + maxUnavailable: 0 + template: + metadata: + labels: + app: synthetix-indexer + network: optimism-mainnet + spec: + containers: + - name: indexer + image: ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/synthetix-data/indexer:latest-optimism-mainnet + imagePullPolicy: Always + resources: + limits: + cpu: "1" + memory: "2Gi" + requests: + cpu: "500m" + memory: "1Gi" + ports: + - containerPort: 4350 + name: gql + env: + - name: DB_HOST + valueFrom: + configMapKeyRef: + name: db-config + key: db-host + - name: DB_PORT + valueFrom: + configMapKeyRef: + name: db-config + key: db-port + - name: DB_NAME + value: "optimism_mainnet" + - name: DB_PASS + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: password + - name: DB_USER + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: username + - name: GQL_PORT + value: "4350" + - name: RPC_ENDPOINT + valueFrom: + configMapKeyRef: + name: db-config + key: optimism-mainnet-rpc + - name: API_KEY + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: conduit-api-key + readinessProbe: + httpGet: + path: /health + port: 4350 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /health + port: 4350 + initialDelaySeconds: 60 + periodSeconds: 20 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + securityContext: + runAsNonRoot: true + runAsUser: 1000 + fsGroup: 1000 + terminationGracePeriodSeconds: 60 diff --git a/k8s/deployments/snax-mainnet.yaml b/k8s/deployments/snax-mainnet.yaml new file mode 100644 index 00000000..f2e8c026 --- /dev/null +++ b/k8s/deployments/snax-mainnet.yaml @@ -0,0 +1,97 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: indexer-snax-mainnet + namespace: synthetix-data + labels: + app: synthetix-indexer + network: snax-mainnet +spec: + replicas: 1 + selector: + matchLabels: + app: synthetix-indexer + network: snax-mainnet + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 1 + maxUnavailable: 0 + template: + metadata: + labels: + app: synthetix-indexer + network: snax-mainnet + spec: + containers: + - name: indexer + image: ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/synthetix-data/indexer:latest-snax-mainnet + imagePullPolicy: Always + resources: + limits: + cpu: "1" + memory: "2Gi" + requests: + cpu: "500m" + memory: "1Gi" + ports: + - containerPort: 4350 + name: gql + env: + - name: DB_HOST + valueFrom: + configMapKeyRef: + name: db-config + key: db-host + - name: DB_PORT + valueFrom: + configMapKeyRef: + name: db-config + key: db-port + - name: DB_NAME + value: "snax_mainnet" + - name: DB_PASS + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: password + - name: DB_USER + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: username + - name: GQL_PORT + value: "4350" + - name: RPC_ENDPOINT + valueFrom: + configMapKeyRef: + name: db-config + key: snax-mainnet-rpc + - name: API_KEY + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: conduit-api-key + readinessProbe: + httpGet: + path: /health + port: 4350 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /health + port: 4350 + initialDelaySeconds: 60 + periodSeconds: 20 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + securityContext: + runAsNonRoot: true + runAsUser: 1000 + fsGroup: 1000 + terminationGracePeriodSeconds: 60 diff --git a/k8s/deployments/snax-testnet.yaml b/k8s/deployments/snax-testnet.yaml new file mode 100644 index 00000000..474dac87 --- /dev/null +++ b/k8s/deployments/snax-testnet.yaml @@ -0,0 +1,97 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: indexer-snax-testnet + namespace: synthetix-data + labels: + app: synthetix-indexer + network: snax-testnet +spec: + replicas: 1 + selector: + matchLabels: + app: synthetix-indexer + network: snax-testnet + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 1 + maxUnavailable: 0 + template: + metadata: + labels: + app: synthetix-indexer + network: snax-testnet + spec: + containers: + - name: indexer + image: ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/synthetix-data/indexer:latest-snax-testnet + imagePullPolicy: Always + resources: + limits: + cpu: "1" + memory: "2Gi" + requests: + cpu: "500m" + memory: "1Gi" + ports: + - containerPort: 4350 + name: gql + env: + - name: DB_HOST + valueFrom: + configMapKeyRef: + name: db-config + key: db-host + - name: DB_PORT + valueFrom: + configMapKeyRef: + name: db-config + key: db-port + - name: DB_NAME + value: "snax_testnet" + - name: DB_PASS + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: password + - name: DB_USER + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: username + - name: GQL_PORT + value: "4350" + - name: RPC_ENDPOINT + valueFrom: + configMapKeyRef: + name: db-config + key: snax-testnet-rpc + - name: API_KEY + valueFrom: + secretKeyRef: + name: aurora-db-credentials + key: conduit-api-key + readinessProbe: + httpGet: + path: /health + port: 4350 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /health + port: 4350 + initialDelaySeconds: 60 + periodSeconds: 20 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + securityContext: + runAsNonRoot: true + runAsUser: 1000 + fsGroup: 1000 + terminationGracePeriodSeconds: 60 diff --git a/k8s/external-secrets.yaml b/k8s/external-secrets.yaml new file mode 100644 index 00000000..6dc61cad --- /dev/null +++ b/k8s/external-secrets.yaml @@ -0,0 +1,30 @@ +apiVersion: external-secrets.io/v1beta1 +kind: ClusterSecretStore +metadata: + name: aws-secretsmanager +spec: + provider: + aws: + service: SecretsManager + region: us-east-1 # Change to your AWS region + auth: + jwt: + serviceAccountRef: + name: external-secrets-sa + namespace: synthetix-data +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: external-secrets-sa + namespace: synthetix-data + annotations: + eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT_ID:role/EksExternalSecretsRole +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: indexer-service-account + namespace: synthetix-data + annotations: + eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT_ID:role/EksIndexerServiceRole \ No newline at end of file diff --git a/scripts/generate-deployments.sh b/scripts/generate-deployments.sh new file mode 100755 index 00000000..4702cf8f --- /dev/null +++ b/scripts/generate-deployments.sh @@ -0,0 +1,136 @@ +#!/bin/bash + +# Create directories if they don't exist +mkdir -p k8s/deployments + +# First, create the template file +cat > k8s/deployment-template.yaml < Date: Tue, 18 Mar 2025 00:13:19 +1100 Subject: [PATCH 03/25] updating pipeline --- .circleci/config.yml | 11 +++++------ .gitignore | 3 ++- .../mage_data/Synthetix/mage-ai.db | Bin 561152 -> 0 bytes 3 files changed, 7 insertions(+), 7 deletions(-) delete mode 100644 transformers-mage/mage_data/Synthetix/mage-ai.db diff --git a/.circleci/config.yml b/.circleci/config.yml index d64435a1..a3fef617 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -32,7 +32,7 @@ jobs: - aws-cli/setup: role-arn: ${AWS_ROLE_ARN} - aws-region: << pipeline.parameters.aws-region >> + aws-region: ${AWS_REGION} # Build and push Docker image for specific network - aws-ecr/build-and-push-image: @@ -40,7 +40,7 @@ jobs: aws-secret-access-key: ${AWS_SECRET_ACCESS_KEY} account-url: ${AWS_ECR_ACCOUNT_URL} repo: << pipeline.parameters.ecr-repository-prefix >> - region: << pipeline.parameters.aws-region >> + region: ${AWS_REGION} tag: "${CIRCLE_SHA1}-<< parameters.network >>,latest-<< parameters.network >>" path: ./indexers/<< parameters.network >> dockerfile: ./indexers/<< parameters.network >>/Dockerfile @@ -52,13 +52,13 @@ jobs: - checkout - aws-cli/setup: role-arn: ${AWS_ROLE_ARN} - aws-region: << pipeline.parameters.aws-region >> + aws-region: ${AWS_REGION} - kubernetes/install-kubectl - aws-eks/update-kubeconfig-with-authenticator: cluster-name: << pipeline.parameters.eks-cluster-name >> - aws-region: << pipeline.parameters.aws-region >> + aws-region: ${AWS_REGION} # Get Aurora DB endpoint from CloudFormation outputs - run: @@ -203,5 +203,4 @@ workflows: - build-and-push-images filters: branches: - only: main - \ No newline at end of file + only: main \ No newline at end of file diff --git a/.gitignore b/.gitignore index bb287801..c1723f87 100644 --- a/.gitignore +++ b/.gitignore @@ -185,4 +185,5 @@ secrets.toml transformers-mage/mage_data folder_contents.txt -.env.tmp \ No newline at end of file +.env.tmp +mage-ai.db diff --git a/transformers-mage/mage_data/Synthetix/mage-ai.db b/transformers-mage/mage_data/Synthetix/mage-ai.db deleted file mode 100644 index b71e92b44603bc9cf133328e39a02b8d6234d57b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 561152 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 Date: Tue, 18 Mar 2025 00:16:47 +1100 Subject: [PATCH 04/25] updating pipeline --- .circleci/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a3fef617..bd21a629 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -15,7 +15,7 @@ parameters: default: "synthetix-data/indexer" eks-cluster-name: type: string - default: "synthetix-eks-cluster" + default: "snx" jobs: build-and-push-images: @@ -32,7 +32,7 @@ jobs: - aws-cli/setup: role-arn: ${AWS_ROLE_ARN} - aws-region: ${AWS_REGION} + aws-region: AWS_REGION # Build and push Docker image for specific network - aws-ecr/build-and-push-image: @@ -52,7 +52,7 @@ jobs: - checkout - aws-cli/setup: role-arn: ${AWS_ROLE_ARN} - aws-region: ${AWS_REGION} + aws-region: AWS_REGION - kubernetes/install-kubectl From 23ba45cf8ea4ae33c22c5f33559855dda7ed5687 Mon Sep 17 00:00:00 2001 From: Peter Hanssens Date: Tue, 18 Mar 2025 00:20:12 +1100 Subject: [PATCH 05/25] updating pipeline --- .circleci/config.yml | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index bd21a629..9f3774a4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -31,19 +31,17 @@ jobs: docker_layer_caching: true - aws-cli/setup: - role-arn: ${AWS_ROLE_ARN} + role-arn: AWS_ROLE_ARN aws-region: AWS_REGION # Build and push Docker image for specific network - aws-ecr/build-and-push-image: - aws-access-key-id: ${AWS_ACCESS_KEY_ID} - aws-secret-access-key: ${AWS_SECRET_ACCESS_KEY} - account-url: ${AWS_ECR_ACCOUNT_URL} + region: AWS_REGION repo: << pipeline.parameters.ecr-repository-prefix >> - region: ${AWS_REGION} tag: "${CIRCLE_SHA1}-<< parameters.network >>,latest-<< parameters.network >>" path: ./indexers/<< parameters.network >> dockerfile: ./indexers/<< parameters.network >>/Dockerfile + registry-id: AWS_ACCOUNT_ID deploy-to-eks: docker: @@ -51,14 +49,14 @@ jobs: steps: - checkout - aws-cli/setup: - role-arn: ${AWS_ROLE_ARN} + role-arn: AWS_ROLE_ARN aws-region: AWS_REGION - kubernetes/install-kubectl - aws-eks/update-kubeconfig-with-authenticator: cluster-name: << pipeline.parameters.eks-cluster-name >> - aws-region: ${AWS_REGION} + aws-region: AWS_REGION # Get Aurora DB endpoint from CloudFormation outputs - run: @@ -82,7 +80,7 @@ jobs: fi # Create or update ConfigMap - cat > db-config.yaml < db-config.yaml \< external-secret.yaml < external-secret.yaml \< Date: Tue, 18 Mar 2025 00:29:29 +1100 Subject: [PATCH 06/25] updating pipeline --- .circleci/config.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 9f3774a4..f1eefb04 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -192,7 +192,8 @@ workflows: ] filters: branches: - only: main + - only: main + - feat/eks-deploy # Deploy to EKS with Aurora integration - deploy-to-eks: From 09f081fa83b748526016665f926873fe1013e2bb Mon Sep 17 00:00:00 2001 From: Peter Hanssens Date: Tue, 18 Mar 2025 00:30:23 +1100 Subject: [PATCH 07/25] updating pipeline --- .circleci/config.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f1eefb04..4cc7c8f8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -192,8 +192,9 @@ workflows: ] filters: branches: - - only: main - - feat/eks-deploy + only: + - main + - feat/eks-deploy # Deploy to EKS with Aurora integration - deploy-to-eks: From 7c204a773c7aeead135b121263eb97a5db99c145 Mon Sep 17 00:00:00 2001 From: Peter Hanssens Date: Tue, 18 Mar 2025 00:31:19 +1100 Subject: [PATCH 08/25] updating pipeline --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4cc7c8f8..d4c3fd47 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -194,7 +194,7 @@ workflows: branches: only: - main - - feat/eks-deploy + - feat/eks # Deploy to EKS with Aurora integration - deploy-to-eks: From 134e5fb9196ebed25037cd951d306fa9bbf5e6e6 Mon Sep 17 00:00:00 2001 From: Peter Hanssens Date: Tue, 18 Mar 2025 00:32:16 +1100 Subject: [PATCH 09/25] updating pipeline --- .circleci/config.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d4c3fd47..ee948571 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -27,7 +27,6 @@ jobs: steps: - checkout - setup_remote_docker: - version: 20.10.14 docker_layer_caching: true - aws-cli/setup: From 9d95681214c47e31bd22abf8e1d572133e27a7ae Mon Sep 17 00:00:00 2001 From: Peter Hanssens Date: Tue, 18 Mar 2025 00:35:17 +1100 Subject: [PATCH 10/25] updating pipeline --- .circleci/config.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ee948571..67410713 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -32,10 +32,11 @@ jobs: - aws-cli/setup: role-arn: AWS_ROLE_ARN aws-region: AWS_REGION + role-session-name: "${CIRCLE_PROJECT_REPONAME}-${CIRCLE_BUILD_NUM}" # Build and push Docker image for specific network - aws-ecr/build-and-push-image: - region: AWS_REGION + region: "${AWS_REGION}" repo: << pipeline.parameters.ecr-repository-prefix >> tag: "${CIRCLE_SHA1}-<< parameters.network >>,latest-<< parameters.network >>" path: ./indexers/<< parameters.network >> @@ -50,12 +51,13 @@ jobs: - aws-cli/setup: role-arn: AWS_ROLE_ARN aws-region: AWS_REGION + role-session-name: "${CIRCLE_PROJECT_REPONAME}-${CIRCLE_BUILD_NUM}" - kubernetes/install-kubectl - aws-eks/update-kubeconfig-with-authenticator: cluster-name: << pipeline.parameters.eks-cluster-name >> - aws-region: AWS_REGION + aws-region: "${AWS_REGION}" # Get Aurora DB endpoint from CloudFormation outputs - run: From 68cc4a1754fbc1e105026946c2613d8d1a81a52d Mon Sep 17 00:00:00 2001 From: Peter Hanssens Date: Tue, 18 Mar 2025 00:37:17 +1100 Subject: [PATCH 11/25] updating pipeline --- .circleci/config.yml | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 67410713..01625b3b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,6 +10,9 @@ parameters: aws-region: type: string default: "us-east-1" + aws-role-arn: + type: string + default: "arn:aws:iam::${AWS_ACCOUNT_ID}:role/CircleCI-OIDC-Role" ecr-repository-prefix: type: string default: "synthetix-data/indexer" @@ -31,13 +34,12 @@ jobs: - aws-cli/setup: role-arn: AWS_ROLE_ARN - aws-region: AWS_REGION - role-session-name: "${CIRCLE_PROJECT_REPONAME}-${CIRCLE_BUILD_NUM}" + aws-region: AWS_DEFAULT_REGION # Build and push Docker image for specific network - aws-ecr/build-and-push-image: - region: "${AWS_REGION}" - repo: << pipeline.parameters.ecr-repository-prefix >> + region: ${AWS_DEFAULT_REGION} + repo: synthetix-data/indexer tag: "${CIRCLE_SHA1}-<< parameters.network >>,latest-<< parameters.network >>" path: ./indexers/<< parameters.network >> dockerfile: ./indexers/<< parameters.network >>/Dockerfile @@ -50,14 +52,13 @@ jobs: - checkout - aws-cli/setup: role-arn: AWS_ROLE_ARN - aws-region: AWS_REGION - role-session-name: "${CIRCLE_PROJECT_REPONAME}-${CIRCLE_BUILD_NUM}" + aws-region: AWS_DEFAULT_REGION - kubernetes/install-kubectl - aws-eks/update-kubeconfig-with-authenticator: - cluster-name: << pipeline.parameters.eks-cluster-name >> - aws-region: "${AWS_REGION}" + cluster-name: snx + aws-region: ${AWS_DEFAULT_REGION} # Get Aurora DB endpoint from CloudFormation outputs - run: From 2a14fa0e4b00df2fd9d53df0458b2df21ff3187c Mon Sep 17 00:00:00 2001 From: Peter Hanssens Date: Tue, 18 Mar 2025 00:40:24 +1100 Subject: [PATCH 12/25] updating pipeline --- .circleci/config.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 01625b3b..a79ab72c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -33,12 +33,13 @@ jobs: docker_layer_caching: true - aws-cli/setup: - role-arn: AWS_ROLE_ARN - aws-region: AWS_DEFAULT_REGION + aws-access-key-id: AWS_ACCESS_KEY_ID + aws-secret-access-key: AWS_SECRET_ACCESS_KEY + aws-region: AWS_REGION # Build and push Docker image for specific network - aws-ecr/build-and-push-image: - region: ${AWS_DEFAULT_REGION} + region: ${AWS_REGION} repo: synthetix-data/indexer tag: "${CIRCLE_SHA1}-<< parameters.network >>,latest-<< parameters.network >>" path: ./indexers/<< parameters.network >> @@ -51,14 +52,15 @@ jobs: steps: - checkout - aws-cli/setup: - role-arn: AWS_ROLE_ARN - aws-region: AWS_DEFAULT_REGION + aws-access-key-id: AWS_ACCESS_KEY_ID + aws-secret-access-key: AWS_SECRET_ACCESS_KEY + aws-region: AWS_REGION - kubernetes/install-kubectl - aws-eks/update-kubeconfig-with-authenticator: cluster-name: snx - aws-region: ${AWS_DEFAULT_REGION} + aws-region: ${AWS_REGION} # Get Aurora DB endpoint from CloudFormation outputs - run: From 11c465b91e56ff0f54f40b4d1b2363d54e3ebe2f Mon Sep 17 00:00:00 2001 From: Peter Hanssens Date: Tue, 18 Mar 2025 00:49:30 +1100 Subject: [PATCH 13/25] updating pipeline --- .circleci/config.yml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a79ab72c..e66a608a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,7 +2,7 @@ version: 2.1 orbs: aws-cli: circleci/aws-cli@3.1 - aws-ecr: circleci/aws-ecr@8.2.1 + aws-ecr: circleci/aws-ecr@9.4.0 aws-eks: circleci/aws-eks@2.2.0 kubernetes: circleci/kubernetes@1.3 @@ -38,13 +38,18 @@ jobs: aws-region: AWS_REGION # Build and push Docker image for specific network - - aws-ecr/build-and-push-image: + - aws-ecr/build_and_push_image: + account_id: AWS_ACCOUNT_ID + auth: + - aws-cli/setup: + aws-access-key-id: AWS_ACCESS_KEY_ID + aws-secret-access-key: AWS_SECRET_ACCESS_KEY + aws-region: AWS_REGION region: ${AWS_REGION} repo: synthetix-data/indexer tag: "${CIRCLE_SHA1}-<< parameters.network >>,latest-<< parameters.network >>" path: ./indexers/<< parameters.network >> dockerfile: ./indexers/<< parameters.network >>/Dockerfile - registry-id: AWS_ACCOUNT_ID deploy-to-eks: docker: From b30c151979964d33f270146a753e5e89c9b479c8 Mon Sep 17 00:00:00 2001 From: Peter Hanssens Date: Tue, 18 Mar 2025 00:51:15 +1100 Subject: [PATCH 14/25] updating pipeline --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index e66a608a..1f51070a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -47,7 +47,7 @@ jobs: aws-region: AWS_REGION region: ${AWS_REGION} repo: synthetix-data/indexer - tag: "${CIRCLE_SHA1}-<< parameters.network >>,latest-<< parameters.network >>" + tag: "${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/synthetix-data/indexer:${CIRCLE_SHA1}-<< parameters.network >>,latest-<< parameters.network >>" path: ./indexers/<< parameters.network >> dockerfile: ./indexers/<< parameters.network >>/Dockerfile From 923658027bcb0622c33dd3c4e1a3e2db8c4908af Mon Sep 17 00:00:00 2001 From: Peter Hanssens Date: Tue, 18 Mar 2025 00:56:41 +1100 Subject: [PATCH 15/25] updating pipeline --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1f51070a..794fd6e8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -46,8 +46,8 @@ jobs: aws-secret-access-key: AWS_SECRET_ACCESS_KEY aws-region: AWS_REGION region: ${AWS_REGION} - repo: synthetix-data/indexer - tag: "${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/synthetix-data/indexer:${CIRCLE_SHA1}-<< parameters.network >>,latest-<< parameters.network >>" + repo: mage-synthetix-prod-<< parameters.network >> + tag: "${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/mage-synthetix-prod-<< parameters.network >>:${CIRCLE_SHA1}-<< parameters.network >>,latest-<< parameters.network >>" path: ./indexers/<< parameters.network >> dockerfile: ./indexers/<< parameters.network >>/Dockerfile From 13ce0c7f44530e75c38ed948ae6462a22c5e6616 Mon Sep 17 00:00:00 2001 From: Peter Hanssens Date: Tue, 18 Mar 2025 00:58:59 +1100 Subject: [PATCH 16/25] updating pipeline --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 794fd6e8..a6b869b9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -47,7 +47,7 @@ jobs: aws-region: AWS_REGION region: ${AWS_REGION} repo: mage-synthetix-prod-<< parameters.network >> - tag: "${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/mage-synthetix-prod-<< parameters.network >>:${CIRCLE_SHA1}-<< parameters.network >>,latest-<< parameters.network >>" + tag: "218790491775.dkr.ecr.us-east-1.amazonaws.com/mage-synthetix-prod-<< parameters.network >>:${CIRCLE_SHA1}-<< parameters.network >>,latest-<< parameters.network >>" path: ./indexers/<< parameters.network >> dockerfile: ./indexers/<< parameters.network >>/Dockerfile From 5f3b94c2a2c5a809a87d302ed254baca754bf962 Mon Sep 17 00:00:00 2001 From: Peter Hanssens Date: Tue, 18 Mar 2025 01:01:30 +1100 Subject: [PATCH 17/25] updating pipeline --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a6b869b9..fbb38a58 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -46,8 +46,8 @@ jobs: aws-secret-access-key: AWS_SECRET_ACCESS_KEY aws-region: AWS_REGION region: ${AWS_REGION} - repo: mage-synthetix-prod-<< parameters.network >> - tag: "218790491775.dkr.ecr.us-east-1.amazonaws.com/mage-synthetix-prod-<< parameters.network >>:${CIRCLE_SHA1}-<< parameters.network >>,latest-<< parameters.network >>" + repo: 218790491775.dkr.ecr.us-east-1.amazonaws.com/mage-synthetix-prod-<< parameters.network >> + tag: "${CIRCLE_SHA1},latest" path: ./indexers/<< parameters.network >> dockerfile: ./indexers/<< parameters.network >>/Dockerfile From 636247836727e7c2cb0d38130c69e698d43c4264 Mon Sep 17 00:00:00 2001 From: Peter Hanssens Date: Tue, 18 Mar 2025 08:11:34 +1100 Subject: [PATCH 18/25] updating pipeline --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index fbb38a58..546c1a82 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -47,7 +47,7 @@ jobs: aws-region: AWS_REGION region: ${AWS_REGION} repo: 218790491775.dkr.ecr.us-east-1.amazonaws.com/mage-synthetix-prod-<< parameters.network >> - tag: "${CIRCLE_SHA1},latest" + tag: "latest" path: ./indexers/<< parameters.network >> dockerfile: ./indexers/<< parameters.network >>/Dockerfile From fb499e42c194130c91613a464cc0026e4c254a6f Mon Sep 17 00:00:00 2001 From: Peter Hanssens Date: Tue, 18 Mar 2025 08:14:09 +1100 Subject: [PATCH 19/25] updating pipeline --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 546c1a82..fdc908c7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -45,8 +45,8 @@ jobs: aws-access-key-id: AWS_ACCESS_KEY_ID aws-secret-access-key: AWS_SECRET_ACCESS_KEY aws-region: AWS_REGION - region: ${AWS_REGION} - repo: 218790491775.dkr.ecr.us-east-1.amazonaws.com/mage-synthetix-prod-<< parameters.network >> + region: AWS_REGION + repo: mage-synthetix-prod-<< parameters.network >> tag: "latest" path: ./indexers/<< parameters.network >> dockerfile: ./indexers/<< parameters.network >>/Dockerfile From d45f14cd4822504481de143a9d523685f8b1d6a5 Mon Sep 17 00:00:00 2001 From: Peter Hanssens Date: Tue, 18 Mar 2025 08:26:41 +1100 Subject: [PATCH 20/25] updating pipeline --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index fdc908c7..ed3d908d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -39,13 +39,13 @@ jobs: # Build and push Docker image for specific network - aws-ecr/build_and_push_image: - account_id: AWS_ACCOUNT_ID + account_id: ${AWS_ACCOUNT_ID} auth: - aws-cli/setup: aws-access-key-id: AWS_ACCESS_KEY_ID aws-secret-access-key: AWS_SECRET_ACCESS_KEY aws-region: AWS_REGION - region: AWS_REGION + region: ${AWS_REGION} repo: mage-synthetix-prod-<< parameters.network >> tag: "latest" path: ./indexers/<< parameters.network >> From e4233c66dfd336ee50d5b44a42eeee160a643543 Mon Sep 17 00:00:00 2001 From: Peter Hanssens Date: Tue, 18 Mar 2025 08:29:24 +1100 Subject: [PATCH 21/25] updating pipeline --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ed3d908d..f6fa230f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -49,7 +49,7 @@ jobs: repo: mage-synthetix-prod-<< parameters.network >> tag: "latest" path: ./indexers/<< parameters.network >> - dockerfile: ./indexers/<< parameters.network >>/Dockerfile + dockerfile: Dockerfile deploy-to-eks: docker: From 47e4e709acee4d18256d329eab66d9ce0a287cda Mon Sep 17 00:00:00 2001 From: Peter Hanssens Date: Tue, 18 Mar 2025 08:47:47 +1100 Subject: [PATCH 22/25] updating pipeline --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index f6fa230f..f27eee1b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -48,6 +48,7 @@ jobs: region: ${AWS_REGION} repo: mage-synthetix-prod-<< parameters.network >> tag: "latest" + build_path: ./indexers/<< parameters.network >> path: ./indexers/<< parameters.network >> dockerfile: Dockerfile From 0e8f0034d4b4450b4b8d183be21c57a8179fa925 Mon Sep 17 00:00:00 2001 From: Peter Hanssens Date: Tue, 18 Mar 2025 08:59:02 +1100 Subject: [PATCH 23/25] updating pipeline --- .circleci/config.yml | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f27eee1b..a01acd1b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -179,11 +179,38 @@ jobs: kubectl rollout status deployment/indexer-$network -n synthetix-data --timeout=300s done + build-transformers-mage: + docker: + - image: cimg/base:2023.03 + steps: + - checkout + - setup_remote_docker: + docker_layer_caching: true + - aws-ecr/build_and_push_image: + account_id: ${AWS_ACCOUNT_ID} + region: ${AWS_REGION} + repo: transformers-mage + tag: latest + build_path: ./transformers-mage + path: ./transformers-mage + dockerfile: Dockerfile + auth: + - aws-cli/setup: + aws-access-key-id: AWS_ACCESS_KEY_ID + aws-secret-access-key: AWS_SECRET_ACCESS_KEY + aws-region: AWS_REGION + workflows: version: 2 build-deploy: jobs: - # Build and push images for all networks + - build-transformers-mage: + context: aws-credentials + filters: + branches: + only: + - main + - feat/eks - build-and-push-images: context: aws-credentials matrix: @@ -205,11 +232,10 @@ workflows: only: - main - feat/eks - - # Deploy to EKS with Aurora integration - deploy-to-eks: context: aws-credentials requires: + - build-transformers-mage - build-and-push-images filters: branches: From 00a89762cf7e968bab3eb87fcd3a0cc34d62ddf4 Mon Sep 17 00:00:00 2001 From: Peter Hanssens Date: Tue, 18 Mar 2025 09:06:55 +1100 Subject: [PATCH 24/25] updating pipeline --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a01acd1b..b5d51bf4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -189,7 +189,7 @@ jobs: - aws-ecr/build_and_push_image: account_id: ${AWS_ACCOUNT_ID} region: ${AWS_REGION} - repo: transformers-mage + repo: mage-synthetix-prod-image tag: latest build_path: ./transformers-mage path: ./transformers-mage From f837d7049fa865bae7c36861bc3ccef698f263d3 Mon Sep 17 00:00:00 2001 From: Peter Hanssens Date: Tue, 18 Mar 2025 09:14:11 +1100 Subject: [PATCH 25/25] disable dbt docs for now --- .github/workflows/docs.yml | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 3c9b2f35..e5b03d60 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -25,20 +25,20 @@ jobs: - name: Install python dependencies run: | cd transformers && pip install -I --force-reinstall setuptools==71.0.0 && pip install --no-build-isolation --no-cache-dir -r requirements.txt - - name: Install dbt dependencies - run: | - cd transformers/synthetix && dbt deps - - name: Build docs - run: | - cd transformers/synthetix && dbt docs generate --profiles-dir profiles --profile synthetix-host - env: - PG_HOST: ${{ secrets.PG_HOST }} - PG_PASSWORD: ${{ secrets.PG_PASSWORD }} - - name: Deploy to GitHub Pages - uses: peaceiris/actions-gh-pages@v3 - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} - with: - publish_branch: gh-pages - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: transformers/synthetix/target - force_orphan: true + # - name: Install dbt dependencies + # run: | + # cd transformers/synthetix && dbt deps + # - name: Build docs + # run: | + # cd transformers/synthetix && dbt docs generate --profiles-dir profiles --profile synthetix-host + # env: + # PG_HOST: ${{ secrets.PG_HOST }} + # PG_PASSWORD: ${{ secrets.PG_PASSWORD }} + # - name: Deploy to GitHub Pages + # uses: peaceiris/actions-gh-pages@v3 + # if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} + # with: + # publish_branch: gh-pages + # github_token: ${{ secrets.GITHUB_TOKEN }} + # publish_dir: transformers/synthetix/target + # force_orphan: true