diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..66abcc71 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,30 @@ +name: Release — GitHub release with generated changelog + +# Runs when a semver tag (vX.Y.Z) is pushed. Creates a GitHub release whose +# notes are generated from the merged pull requests since the previous tag. +# `--verify-tag` fails the job if the tag does not exist on the remote. + +on: + push: + tags: + - 'v[0-9]+.[0-9]+.[0-9]+' + +permissions: + contents: write + +jobs: + github-release: + name: Create GitHub release + runs-on: ubuntu-latest + + steps: + - name: Create release with generated notes + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAG: ${{ github.ref_name }} + run: | + gh release create "$TAG" \ + --repo "$GITHUB_REPOSITORY" \ + --verify-tag \ + --title "$TAG" \ + --generate-notes diff --git a/.github/workflows/vercel-preview.yml b/.github/workflows/vercel-preview.yml new file mode 100644 index 00000000..794a63cb --- /dev/null +++ b/.github/workflows/vercel-preview.yml @@ -0,0 +1,75 @@ +name: Frontend — Vercel preview deployment + +# Deploys the frontend (frontend/) to a Vercel preview for every pull request +# that touches it, then comments the preview URL on the PR. +# +# Requires repository secrets: VERCEL_TOKEN, VERCEL_ORG_ID, VERCEL_PROJECT_ID. +# Forked PRs cannot read secrets, so the job is skipped for them. + +on: + pull_request: + paths: + - 'frontend/**' + - 'package-lock.json' + - '.github/workflows/vercel-preview.yml' + +permissions: + contents: read + pull-requests: write + +concurrency: + group: vercel-preview-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + preview: + name: Deploy preview + runs-on: ubuntu-latest + if: github.event.pull_request.head.repo.full_name == github.repository + + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version-file: '.nvmrc' + + - name: Install Vercel CLI + run: npm install --global vercel@latest + + - name: Pull Vercel project settings + working-directory: frontend + env: + VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} + VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} + VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} + run: vercel pull --yes --environment=preview + + - name: Build for preview + working-directory: frontend + env: + VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} + VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} + VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} + run: vercel build + + - name: Deploy prebuilt output + id: deploy + working-directory: frontend + env: + VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} + VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} + VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} + run: echo "url=$(vercel deploy --prebuilt)" >> "$GITHUB_OUTPUT" + + - name: Comment preview URL on the PR + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PREVIEW_URL: ${{ steps.deploy.outputs.url }} + PR_NUMBER: ${{ github.event.pull_request.number }} + run: | + gh pr comment "$PR_NUMBER" \ + --repo "$GITHUB_REPOSITORY" \ + --body "Frontend preview: $PREVIEW_URL" diff --git a/helm/trivela/README.md b/helm/trivela/README.md index fa236274..57b243a7 100644 --- a/helm/trivela/README.md +++ b/helm/trivela/README.md @@ -39,6 +39,7 @@ All configurable values are in [values.yaml](values.yaml). Key overrides: | `backend.image.repository` | `trivela-backend` | Backend image | | `backend.image.tag` | `latest` | Backend image tag | | `frontend.replicaCount` | `2` | Initial frontend pod count | +| `redis.enabled` | `false` | Deploy Redis and set `REDIS_URL` on the backend | | `ingress.host` | `trivela.example.com` | Public hostname | | `ingress.tls.enabled` | `true` | Enable TLS via cert-manager | | `autoscaling.minReplicas` | `2` | HPA minimum replicas | diff --git a/helm/trivela/templates/deployment-backend.yaml b/helm/trivela/templates/deployment-backend.yaml index 83d2d130..79ffeafc 100644 --- a/helm/trivela/templates/deployment-backend.yaml +++ b/helm/trivela/templates/deployment-backend.yaml @@ -52,6 +52,10 @@ spec: secretKeyRef: name: {{ include "trivela.fullname" . }}-secrets key: SOROBAN_RPC_URL + {{- if .Values.redis.enabled }} + - name: REDIS_URL + value: {{ printf "redis://%s-redis:%v" (include "trivela.fullname" .) .Values.redis.port | quote }} + {{- end }} resources: {{- toYaml .Values.backend.resources | nindent 12 }} livenessProbe: diff --git a/helm/trivela/templates/deployment-redis.yaml b/helm/trivela/templates/deployment-redis.yaml new file mode 100644 index 00000000..5c5538fc --- /dev/null +++ b/helm/trivela/templates/deployment-redis.yaml @@ -0,0 +1,35 @@ +{{- if .Values.redis.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "trivela.fullname" . }}-redis + labels: + {{- include "trivela.labels" . | nindent 4 }} + component: redis +spec: + replicas: 1 + selector: + matchLabels: + {{- include "trivela.selectorLabels" . | nindent 6 }} + component: redis + template: + metadata: + labels: + {{- include "trivela.selectorLabels" . | nindent 8 }} + component: redis + spec: + containers: + - name: redis + image: "{{ .Values.redis.image.repository }}:{{ .Values.redis.image.tag }}" + imagePullPolicy: {{ .Values.redis.image.pullPolicy }} + ports: + - containerPort: {{ .Values.redis.port }} + name: redis + readinessProbe: + exec: + command: ['redis-cli', 'ping'] + initialDelaySeconds: 5 + periodSeconds: 10 + resources: + {{- toYaml .Values.redis.resources | nindent 12 }} +{{- end }} diff --git a/helm/trivela/templates/service-redis.yaml b/helm/trivela/templates/service-redis.yaml new file mode 100644 index 00000000..e894b511 --- /dev/null +++ b/helm/trivela/templates/service-redis.yaml @@ -0,0 +1,19 @@ +{{- if .Values.redis.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "trivela.fullname" . }}-redis + labels: + {{- include "trivela.labels" . | nindent 4 }} + component: redis +spec: + type: ClusterIP + selector: + {{- include "trivela.selectorLabels" . | nindent 4 }} + component: redis + ports: + - name: redis + port: {{ .Values.redis.port }} + targetPort: {{ .Values.redis.port }} + protocol: TCP +{{- end }} diff --git a/helm/trivela/values.yaml b/helm/trivela/values.yaml index 7dc56482..240596d3 100644 --- a/helm/trivela/values.yaml +++ b/helm/trivela/values.yaml @@ -74,3 +74,19 @@ secrets: databaseUrl: 'postgresql://trivela_user:CHANGE_ME@postgres:5432/trivela_db' jwtSecret: 'CHANGE_ME_USE_A_STRONG_RANDOM_SECRET' sorobanRpcUrl: 'https://soroban-testnet.stellar.org' + +# ─── Redis (optional; when enabled the backend gets REDIS_URL) ─────────────── +redis: + enabled: false + image: + repository: redis + tag: 7-alpine + pullPolicy: IfNotPresent + port: 6379 + resources: + requests: + cpu: '50m' + memory: '64Mi' + limits: + cpu: '200m' + memory: '256Mi'