@@ -1,12 +0,0 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: backstage-cluster-ro
|
||||
subjects:
|
||||
- namespace: backstage
|
||||
kind: ServiceAccount
|
||||
name: backstage-service-account
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: system:aggregate-to-view
|
||||
@@ -1,44 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: backstage
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: backstage
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: backstage
|
||||
spec:
|
||||
serviceAccountName: backstage-service-account
|
||||
containers:
|
||||
- name: backstage
|
||||
image: backstage
|
||||
command:
|
||||
- /bin/sh
|
||||
args:
|
||||
- '-c'
|
||||
- "APP_CONFIG_app_baseUrl=$$UFFIZZI_URL APP_CONFIG_backend_baseUrl=$$UFFIZZI_URL APP_CONFIG_auth_environment='production' node packages/backend --config app-config.yaml"
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 7007
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: postgres-secrets
|
||||
env:
|
||||
- name: POSTGRES_PORT
|
||||
value: '5432'
|
||||
- name: POSTGRES_HOST
|
||||
value: 'postgres.default.svc.cluster.local'
|
||||
- name: NODE_ENV
|
||||
value: production
|
||||
resources:
|
||||
limits:
|
||||
cpu: 1000m
|
||||
memory: 384Mi
|
||||
requests:
|
||||
cpu: 20m
|
||||
memory: 160Mi
|
||||
@@ -1,20 +0,0 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: backstage
|
||||
spec:
|
||||
ingressClassName: uffizzi
|
||||
rules:
|
||||
- host: backstage.example.com
|
||||
http:
|
||||
paths:
|
||||
- backend:
|
||||
service:
|
||||
name: backstage
|
||||
port:
|
||||
number: 80
|
||||
path: /
|
||||
pathType: Prefix
|
||||
tls:
|
||||
- hosts:
|
||||
- backstage.example.com
|
||||
@@ -1,5 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: backstage-service-account
|
||||
namespace: default
|
||||
@@ -1,11 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: backstage
|
||||
spec:
|
||||
selector:
|
||||
app: backstage
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
targetPort: http
|
||||
@@ -1,12 +0,0 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- backstage-deploy.yaml
|
||||
- backstage-crb.yaml
|
||||
- backstage-ingress.yaml
|
||||
- backstage-sa.yaml
|
||||
- backstage-svc.yaml
|
||||
- pg-svc.yaml
|
||||
- pg-deploy.yaml
|
||||
- pg-secret.yaml
|
||||
- pg-volume.yaml
|
||||
@@ -1,41 +0,0 @@
|
||||
# kubernetes/postgres.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: postgres
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: postgres
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: postgres
|
||||
spec:
|
||||
containers:
|
||||
- name: postgres
|
||||
image: postgres:12-alpine
|
||||
imagePullPolicy: 'IfNotPresent'
|
||||
ports:
|
||||
- containerPort: 5432
|
||||
env:
|
||||
- name: PGDATA
|
||||
value: '/data/pgdata'
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: postgres-secrets
|
||||
resources:
|
||||
limits:
|
||||
cpu: 1000m
|
||||
memory: 256Mi
|
||||
requests:
|
||||
cpu: 10m
|
||||
memory: 96Mi
|
||||
volumeMounts:
|
||||
- mountPath: /data
|
||||
name: postgresdb
|
||||
volumes:
|
||||
- name: postgresdb
|
||||
persistentVolumeClaim:
|
||||
claimName: postgres-storage-claim
|
||||
@@ -1,8 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: postgres-secrets
|
||||
type: Opaque
|
||||
data:
|
||||
POSTGRES_USER: YmFja3N0YWdl
|
||||
POSTGRES_PASSWORD: aHVudGVyMg==
|
||||
@@ -1,9 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: postgres
|
||||
spec:
|
||||
selector:
|
||||
app: postgres
|
||||
ports:
|
||||
- port: 5432
|
||||
@@ -1,10 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: postgres-storage-claim
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 2G
|
||||
@@ -1,297 +0,0 @@
|
||||
app:
|
||||
title: Backstage Uffizzi Environment
|
||||
baseUrl: ${UFFIZZI_URL}
|
||||
|
||||
organization:
|
||||
name: My Company
|
||||
|
||||
backend:
|
||||
baseUrl: ${UFFIZZI_URL}
|
||||
auth:
|
||||
keys:
|
||||
# random mock key for Uffizzi deployments
|
||||
- secret: 5TXvdjVZFxF7qf9K5RAYRDoGrLzJooqa
|
||||
listen:
|
||||
port: 7007
|
||||
database:
|
||||
client: pg
|
||||
connection:
|
||||
host: ${POSTGRES_HOST}
|
||||
port: ${POSTGRES_PORT}
|
||||
user: ${POSTGRES_USER}
|
||||
password: ${POSTGRES_PASSWORD}
|
||||
cors:
|
||||
origin: ${UFFIZZI_URL}
|
||||
methods: [GET, HEAD, PATCH, POST, PUT, DELETE]
|
||||
credentials: true
|
||||
csp:
|
||||
connect-src: ["'self'", 'http:', 'https:']
|
||||
img-src: ["'self'", 'data:', 'https://cdnjs.cloudflare.com']
|
||||
# Content-Security-Policy directives follow the Helmet format: https://helmetjs.github.io/#reference
|
||||
# Default Helmet Content-Security-Policy values can be removed by setting the key to false
|
||||
|
||||
auth:
|
||||
environment: production
|
||||
providers: {}
|
||||
proxy:
|
||||
enabled: true
|
||||
url: https://demo.backstage.io/api/auth
|
||||
|
||||
catalog:
|
||||
rules:
|
||||
- allow:
|
||||
- Component
|
||||
- API
|
||||
- Resource
|
||||
- System
|
||||
- Domain
|
||||
- Location
|
||||
locations:
|
||||
- type: url
|
||||
target: https://github.com/backstage/backstage/blob/${REF_NAME}/packages/catalog-model/examples/all.yaml
|
||||
|
||||
- type: url
|
||||
target: https://github.com/backstage/backstage/blob/${REF_NAME}/plugins/techdocs-backend/examples/documented-component-uffizzi/catalog-info.yaml
|
||||
|
||||
- type: url
|
||||
target: https://github.com/backstage/backstage/blob/${REF_NAME}/packages/catalog-model/examples/acme-corp.yaml
|
||||
rules:
|
||||
- allow: [User, Group]
|
||||
|
||||
- type: url
|
||||
target: https://github.com/backstage/backstage/blob/${REF_NAME}/plugins/scaffolder-backend/sample-templates/all-templates.yaml
|
||||
rules:
|
||||
- allow: [Template]
|
||||
|
||||
proxy:
|
||||
endpoints:
|
||||
'/circleci/api':
|
||||
target: https://circleci.com/api/v1.1
|
||||
headers:
|
||||
Circle-Token: ${CIRCLECI_AUTH_TOKEN}
|
||||
|
||||
'/jenkins/api':
|
||||
target: http://localhost:8080
|
||||
headers:
|
||||
Authorization: ${JENKINS_BASIC_AUTH_HEADER}
|
||||
|
||||
'/travisci/api':
|
||||
target: https://api.travis-ci.com
|
||||
changeOrigin: true
|
||||
headers:
|
||||
Authorization: ${TRAVISCI_AUTH_TOKEN}
|
||||
travis-api-version: '3'
|
||||
|
||||
'/newrelic/apm/api':
|
||||
target: https://api.newrelic.com/v2
|
||||
headers:
|
||||
X-Api-Key: ${NEW_RELIC_REST_API_KEY}
|
||||
|
||||
'/newrelic/api':
|
||||
target: https://api.newrelic.com
|
||||
headers:
|
||||
X-Api-Key: ${NEW_RELIC_USER_KEY}
|
||||
|
||||
'/pagerduty':
|
||||
target: https://api.pagerduty.com
|
||||
headers:
|
||||
Authorization: Token token=${PAGERDUTY_TOKEN}
|
||||
|
||||
'/buildkite/api':
|
||||
target: https://api.buildkite.com/v2/
|
||||
headers:
|
||||
Authorization: ${BUILDKITE_TOKEN}
|
||||
|
||||
'/sentry/api':
|
||||
target: https://sentry.io/api/
|
||||
allowedMethods: ['GET']
|
||||
headers:
|
||||
Authorization: ${SENTRY_TOKEN}
|
||||
|
||||
'/ilert':
|
||||
target: https://api.ilert.com
|
||||
allowedMethods: ['GET', 'POST', 'PUT']
|
||||
allowedHeaders: ['Authorization']
|
||||
headers:
|
||||
Authorization: ${ILERT_AUTH_HEADER}
|
||||
|
||||
'/airflow':
|
||||
target: https://your.airflow.instance.com/api/v1
|
||||
headers:
|
||||
Authorization: ${AIRFLOW_BASIC_AUTH_HEADER}
|
||||
|
||||
'/gocd':
|
||||
target: https://your.gocd.instance.com/go/api
|
||||
allowedMethods: ['GET']
|
||||
allowedHeaders: ['Authorization']
|
||||
headers:
|
||||
Authorization: Basic ${GOCD_AUTH_CREDENTIALS}
|
||||
|
||||
'/dynatrace':
|
||||
target: https://your.dynatrace.instance.com/api/v2
|
||||
headers:
|
||||
Authorization: 'Api-Token ${DYNATRACE_ACCESS_TOKEN}'
|
||||
|
||||
techdocs:
|
||||
builder: 'local' # Alternatives - 'external'
|
||||
generator:
|
||||
runIn: 'local'
|
||||
# dockerImage: my-org/techdocs # use a custom docker image
|
||||
# pullImage: true # or false to disable automatic pulling of image (e.g. if custom docker login is required)
|
||||
publisher:
|
||||
type: 'local' # Alternatives - 'googleGcs' or 'awsS3' or 'azureBlobStorage' or 'openStackSwift'. Read documentation for using alternatives.
|
||||
|
||||
dynatrace:
|
||||
baseUrl: https://your.dynatrace.instance.com
|
||||
|
||||
nomad:
|
||||
addr: 0.0.0.0
|
||||
|
||||
# Score-cards sample configuration.
|
||||
scorecards:
|
||||
jsonDataUrl: https://raw.githubusercontent.com/Oriflame/backstage-plugins/main/plugins/score-card/sample-data/
|
||||
wikiLinkTemplate: https://link-to-wiki/{id}
|
||||
|
||||
sentry:
|
||||
organization: my-company
|
||||
|
||||
rollbar:
|
||||
organization: my-company
|
||||
# NOTE: The rollbar-backend & accountToken key may be deprecated in the future (replaced by a proxy config)
|
||||
accountToken: my-rollbar-account-token
|
||||
|
||||
lighthouse:
|
||||
baseUrl: http://localhost:3003
|
||||
|
||||
kubernetes:
|
||||
serviceLocatorMethod:
|
||||
type: 'multiTenant'
|
||||
clusterLocatorMethods:
|
||||
- type: 'config'
|
||||
clusters:
|
||||
- url: ${UFFIZZI_CLUSTER_APISERVER}
|
||||
name: uffizzi
|
||||
authProvider: 'serviceAccount'
|
||||
|
||||
kafka:
|
||||
clientId: backstage
|
||||
clusters:
|
||||
- name: cluster
|
||||
dashboardUrl: https://akhq.io/
|
||||
brokers:
|
||||
- localhost:9092
|
||||
|
||||
allure:
|
||||
baseUrl: http://localhost:5050/allure-docker-service
|
||||
|
||||
integrations:
|
||||
github:
|
||||
- host: github.com
|
||||
token: ${GITHUB_TOKEN}
|
||||
### Example for how to add your GitHub Enterprise instance using the API:
|
||||
# - host: ghe.example.net
|
||||
# apiBaseUrl: https://ghe.example.net/api/v3
|
||||
# token: ${GHE_TOKEN}
|
||||
### Example for how to add your GitHub Enterprise instance using raw HTTP fetches (token is optional):
|
||||
# - host: ghe.example.net
|
||||
# rawBaseUrl: https://ghe.example.net/raw
|
||||
# token: ${GHE_TOKEN}
|
||||
gitlab:
|
||||
- host: gitlab.com
|
||||
token: ${GITLAB_TOKEN}
|
||||
### Example for how to add a bitbucket cloud integration
|
||||
# bitbucketCloud:
|
||||
# - username: ${BITBUCKET_USERNAME}
|
||||
# appPassword: ${BITBUCKET_APP_PASSWORD}
|
||||
### Example for how to add your bitbucket server instance using the API:
|
||||
# - host: server.bitbucket.com
|
||||
# apiBaseUrl: server.bitbucket.com
|
||||
# username: ${BITBUCKET_SERVER_USERNAME}
|
||||
# appPassword: ${BITBUCKET_SERVER_APP_PASSWORD}
|
||||
azure:
|
||||
- host: dev.azure.com
|
||||
token: ${AZURE_TOKEN}
|
||||
# googleGcs:
|
||||
# clientEmail: 'example@example.com'
|
||||
# privateKey: ${GCS_PRIVATE_KEY}
|
||||
awsS3:
|
||||
- host: amazonaws.com
|
||||
accessKeyId: ${AWS_ACCESS_KEY_ID}
|
||||
secretAccessKey: ${AWS_SECRET_ACCESS_KEY}
|
||||
|
||||
costInsights:
|
||||
engineerCost: 200000
|
||||
engineerThreshold: 0.5
|
||||
products:
|
||||
computeEngine:
|
||||
name: Compute Engine
|
||||
icon: compute
|
||||
cloudDataflow:
|
||||
name: Cloud Dataflow
|
||||
icon: data
|
||||
cloudStorage:
|
||||
name: Cloud Storage
|
||||
icon: storage
|
||||
bigQuery:
|
||||
name: BigQuery
|
||||
icon: search
|
||||
events:
|
||||
name: Events
|
||||
icon: data
|
||||
metrics:
|
||||
DAU:
|
||||
name: Daily Active Users
|
||||
default: true
|
||||
MSC:
|
||||
name: Monthly Subscribers
|
||||
currencies:
|
||||
engineers:
|
||||
label: 'Engineers 🛠'
|
||||
unit: 'engineer'
|
||||
usd:
|
||||
label: 'US Dollars 💵'
|
||||
kind: 'USD'
|
||||
unit: 'dollar'
|
||||
prefix: '$'
|
||||
rate: 1
|
||||
carbonOffsetTons:
|
||||
label: 'Carbon Offset Tons ♻️⚖️s'
|
||||
kind: 'CARBON_OFFSET_TONS'
|
||||
unit: 'carbon offset ton'
|
||||
rate: 3.5
|
||||
beers:
|
||||
label: 'Beers 🍺'
|
||||
kind: 'BEERS'
|
||||
unit: 'beer'
|
||||
rate: 4.5
|
||||
pintsIceCream:
|
||||
label: 'Pints of Ice Cream 🍦'
|
||||
kind: 'PINTS_OF_ICE_CREAM'
|
||||
unit: 'ice cream pint'
|
||||
rate: 5.5
|
||||
pagerduty:
|
||||
eventsBaseUrl: 'https://events.pagerduty.com/v2'
|
||||
jenkins:
|
||||
instances:
|
||||
- name: default
|
||||
baseUrl: https://jenkins.example.com
|
||||
username: backstage-bot
|
||||
apiKey: 123456789abcdef0123456789abcedf012
|
||||
|
||||
azureDevOps:
|
||||
host: dev.azure.com
|
||||
token: my-token
|
||||
organization: my-company
|
||||
|
||||
apacheAirflow:
|
||||
baseUrl: https://your.airflow.instance.com
|
||||
|
||||
gocd:
|
||||
baseUrl: https://your.gocd.instance.com
|
||||
|
||||
permission:
|
||||
enabled: true
|
||||
|
||||
search:
|
||||
query:
|
||||
pageLimit: 50
|
||||
@@ -435,7 +435,6 @@ transpilers
|
||||
truthy
|
||||
TSDoc
|
||||
typeahead
|
||||
Uffizzi
|
||||
ui
|
||||
unbreak
|
||||
Unconference
|
||||
|
||||
@@ -1,133 +0,0 @@
|
||||
name: Preview (build)
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, closed]
|
||||
paths-ignore:
|
||||
- '.changeset/**'
|
||||
- 'contrib/**'
|
||||
- 'docs/**'
|
||||
- 'microsite/**'
|
||||
- 'beps/**'
|
||||
- 'scripts/**'
|
||||
- 'storybook/**'
|
||||
- '**/*.test.*'
|
||||
- '**/package.json'
|
||||
- '*.md'
|
||||
|
||||
jobs:
|
||||
build-backstage:
|
||||
env:
|
||||
NODE_OPTIONS: --max-old-space-size=4096
|
||||
UFFIZZI_URL: https://app.uffizzi.com
|
||||
name: Build PR image
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event_name != 'pull_request' || github.event.action != 'closed' }}
|
||||
outputs:
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- name: checkout
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
|
||||
- name: setup-node
|
||||
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
with:
|
||||
node-version: 18.x
|
||||
registry-url: https://registry.npmjs.org/
|
||||
|
||||
- name: yarn install
|
||||
uses: backstage/actions/yarn-install@af61233abb88019335b07ab855873d991f43d25a # v0.6.7
|
||||
with:
|
||||
cache-prefix: linux-v18
|
||||
|
||||
- name: Use Uffizzi's backstage app config
|
||||
run: |
|
||||
cp -f ./.github/uffizzi/uffizzi.production.app-config.yaml ./app-config.yaml
|
||||
|
||||
- name: backstage build
|
||||
run: |
|
||||
yarn workspace example-backend build
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0
|
||||
|
||||
- name: Generate UUID image name
|
||||
id: uuid
|
||||
run: echo "UUID_TAG_APP=backstage-$(uuidgen --time)" >> $GITHUB_ENV
|
||||
|
||||
- name: Docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1
|
||||
with:
|
||||
images: registry.uffizzi.com/${{ env.UUID_TAG_APP }}
|
||||
tags: type=raw,value=60d
|
||||
|
||||
- name: Build Image
|
||||
uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
|
||||
with:
|
||||
context: .
|
||||
file: packages/backend/Dockerfile
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
push: true
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
render-kustomize:
|
||||
name: Render Kustomize Manifests
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- build-backstage
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- name: Checkout git repo
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- name: Render Compose File
|
||||
run: |
|
||||
# update image after the build above
|
||||
cd ./.github/uffizzi/k8s/manifests
|
||||
kustomize edit set image backstage=${{ needs.build-backstage.outputs.tags }}
|
||||
kustomize build . > manifests.rendered.yml
|
||||
cat manifests.rendered.yml
|
||||
|
||||
- name: clone artifacts into current directory
|
||||
run: |
|
||||
cat ${{ github.event_path }} > event.json
|
||||
cp ./.github/uffizzi/k8s/manifests/manifests.rendered.yml manifests.rendered.yml
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4
|
||||
with:
|
||||
name: preview-spec
|
||||
path: |
|
||||
manifests.rendered.yml
|
||||
event.json
|
||||
retention-days: 2
|
||||
overwrite: true
|
||||
|
||||
delete-preview:
|
||||
name: Call for Preview Deletion
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.action == 'closed' }}
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
# If this PR is closing, we will not render a compose file nor pass it to the next workflow.
|
||||
- name: Upload PR Event as Artifact
|
||||
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
|
||||
with:
|
||||
name: preview-spec
|
||||
path: ${{ github.event_path }}
|
||||
retention-days: 2
|
||||
overwrite: true
|
||||
@@ -1,238 +0,0 @@
|
||||
name: Preview (deploy)
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows:
|
||||
- 'Preview (build)'
|
||||
types:
|
||||
- completed
|
||||
|
||||
jobs:
|
||||
cache-manifests-file:
|
||||
name: Cache Manifests File
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||
permissions:
|
||||
# "If you specify the access for any of these scopes, all of those that are not specified are set to none."
|
||||
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
|
||||
actions: read # Access cache
|
||||
outputs:
|
||||
manifests-cache-key: ${{ steps.hash.outputs.MANIFESTS_FILE_HASH }}
|
||||
git-ref: ${{ steps.event.outputs.GIT_REF }}
|
||||
pr-number: ${{ steps.event.outputs.PR_NUMBER }}
|
||||
action: ${{ steps.event.outputs.ACTION }}
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
|
||||
with:
|
||||
disable-sudo: true
|
||||
egress-policy: block
|
||||
allowed-endpoints: >
|
||||
api.github.com:443
|
||||
|
||||
- name: 'Download artifacts'
|
||||
# Fetch output (zip archive) from the workflow run that triggered this workflow.
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
with:
|
||||
script: |
|
||||
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
run_id: context.payload.workflow_run.id,
|
||||
});
|
||||
let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => {
|
||||
return artifact.name == "preview-spec"
|
||||
})[0];
|
||||
if (matchArtifact === undefined) {
|
||||
throw TypeError('Build Artifact not found!');
|
||||
}
|
||||
let download = await github.rest.actions.downloadArtifact({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
artifact_id: matchArtifact.id,
|
||||
archive_format: 'zip',
|
||||
});
|
||||
let fs = require('fs');
|
||||
fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/preview-spec.zip`, Buffer.from(download.data));
|
||||
|
||||
- name: 'Accept event from first stage'
|
||||
run: unzip preview-spec.zip event.json
|
||||
|
||||
- name: Read Event into ENV
|
||||
id: event
|
||||
run: |
|
||||
echo PR_NUMBER=$(jq '.number | tonumber' < event.json) >> $GITHUB_OUTPUT
|
||||
echo ACTION=$(jq --raw-output '.action | tostring | [scan("\\w+")][0]' < event.json) >> $GITHUB_OUTPUT
|
||||
echo GIT_REF=$(jq --raw-output '.pull_request.head.sha | tostring | [scan("\\w+")][0]' < event.json) >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Hash Rendered Manifests File
|
||||
id: hash
|
||||
# If the previous workflow was triggered by a PR close event, we will not have a manifests file artifact.
|
||||
if: ${{ steps.event.outputs.ACTION != 'closed' }}
|
||||
run: |
|
||||
unzip preview-spec.zip manifests.rendered.yml
|
||||
ls
|
||||
echo "MANIFESTS_FILE_HASH=$(md5sum manifests.rendered.yml | awk '{ print $1 }')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Cache Manifests File
|
||||
if: ${{ steps.event.outputs.ACTION != 'closed' }}
|
||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
|
||||
with:
|
||||
path: manifests.rendered.yml
|
||||
key: ${{ steps.hash.outputs.MANIFESTS_FILE_HASH }}
|
||||
|
||||
- name: DEBUG - Print Job Outputs
|
||||
if: ${{ runner.debug }}
|
||||
run: |
|
||||
echo "PR number: ${{ steps.event.outputs.PR_NUMBER }}"
|
||||
echo "Git Ref: ${{ steps.event.outputs.GIT_REF }}"
|
||||
echo "Action: ${{ steps.event.outputs.ACTION }}"
|
||||
echo "Manifests file hash: ${{ steps.hash.outputs.MANIFESTS_FILE_HASH }}"
|
||||
cat event.json
|
||||
|
||||
deploy-uffizzi-preview:
|
||||
name: Deploy to Uffizzi Virtual Cluster
|
||||
needs:
|
||||
- cache-manifests-file
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' && needs.cache-manifests-file.outputs.action != 'closed' }}
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
id-token: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||
|
||||
# Identify comment to be updated
|
||||
- name: Find comment for Ephemeral Environment
|
||||
uses: peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e # v3
|
||||
id: find-comment
|
||||
with:
|
||||
issue-number: ${{ needs.cache-manifests-file.outputs.pr-number }}
|
||||
comment-author: 'github-actions[bot]'
|
||||
body-includes: pr-${{ needs.cache-manifests-file.outputs.pr-number }}
|
||||
direction: last
|
||||
|
||||
# Create/Update comment with action deployment status
|
||||
- name: Create or Update Comment with Deployment Notification
|
||||
id: notification
|
||||
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4
|
||||
with:
|
||||
comment-id: ${{ steps.find-comment.outputs.comment-id }}
|
||||
issue-number: ${{ needs.cache-manifests-file.outputs.pr-number }}
|
||||
body: |
|
||||
## Uffizzi Ephemeral Environment - Virtual Cluster
|
||||
|
||||
:cloud: deploying cluster `pr-${{ needs.cache-manifests-file.outputs.pr-number }}`
|
||||
|
||||
:gear: Updating now by workflow run [${{ github.run_id }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}).
|
||||
|
||||
Download the Uffizzi CLI to interact with the upcoming virtual cluster
|
||||
https://docs.uffizzi.com/install
|
||||
edit-mode: replace
|
||||
|
||||
- name: Connect to Virtual Cluster
|
||||
uses: UffizziCloud/cluster-action@main
|
||||
with:
|
||||
cluster-name: pr-${{ needs.cache-manifests-file.outputs.pr-number }}
|
||||
server: https://app.uffizzi.com
|
||||
|
||||
- name: Fetch cached Manifests File
|
||||
id: cache
|
||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4
|
||||
with:
|
||||
path: manifests.rendered.yml
|
||||
key: ${{ needs.cache-manifests-file.outputs.manifests-cache-key }}
|
||||
|
||||
- name: Kustomize and Apply Manifests
|
||||
id: prev
|
||||
run: |
|
||||
# Apply kustomized manifests to virtual cluster.
|
||||
export KUBECONFIG=`pwd`/kubeconfig
|
||||
kubectl apply -f manifests.rendered.yml --kubeconfig ./kubeconfig
|
||||
# Allow uffizzi to sync the resources
|
||||
sleep 10
|
||||
# Get the hostnames assigned by uffizzi
|
||||
export BACKSTAGE_HOST=$(kubectl get ingress backstage --kubeconfig kubeconfig -o json | jq '.spec.rules[0].host' | tr -d '"')
|
||||
export UFFIZZI_CLUSTER_APISERVER=$(kubectl config view --minify | grep server | cut -f 2- -d ":" | tr -d " ")
|
||||
# Patch backstage deployment to use UFFIZZI_URL
|
||||
kubectl patch deployment backstage --kubeconfig kubeconfig -p '{"spec": {"template": {"spec": {"containers": [{"name": "backstage", "args":["-c", "APP_CONFIG_app_baseUrl='https://${BACKSTAGE_HOST}' APP_CONFIG_backend_baseUrl='https://${BACKSTAGE_HOST}' APP_CONFIG_auth_environment='production' node packages/backend --config app-config.yaml"], "env": [{"name": "UFFIZZI_URL", "value": "'https://${BACKSTAGE_HOST}'"}, {"name": "UFFIZZI_CLUSTER_APISERVER", "value": "'${UFFIZZI_CLUSTER_APISERVER}'"}, {"name": "GITHUB_SHA", "value": "'${GITHUB_SHA}'"}, {"name": "REF_NAME", "value": "'${{ needs.cache-manifests-file.outputs.git-ref }}'"}]}]}}}}'
|
||||
if [[ ${RUNNER_DEBUG} == 1 ]]; then
|
||||
kubectl get all --kubeconfig ./kubeconfig
|
||||
fi
|
||||
echo "backstage_url=${BACKSTAGE_HOST}" >> $GITHUB_OUTPUT
|
||||
echo "Access the \`backstage\` endpoint at [\`${BACKSTAGE_HOST}\`](http://${BACKSTAGE_HOST})" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
- name: Create or Update Comment with Deployment URL
|
||||
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4
|
||||
with:
|
||||
comment-id: ${{ steps.notification.outputs.comment-id }}
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
body: |
|
||||
## Uffizzi Ephemeral Environment - Virtual Cluster
|
||||
|
||||
Your cluster `pr-${{ needs.cache-manifests-file.outputs.pr-number }}` was successfully created. Learn more about [Uffizzi virtual clusters](https://docs.uffizzi.com/topics/virtual-clusters)
|
||||
To connect to this cluster, follow these steps:
|
||||
|
||||
1. Download and install the Uffizzi CLI from https://docs.uffizzi.com/install
|
||||
2. Login to Uffizzi, then select the `backstage` account and project:
|
||||
```
|
||||
uffizzi login
|
||||
```
|
||||
|
||||
```
|
||||
Select an account:
|
||||
‣ ${{ github.event.repository.name }}
|
||||
jdoe
|
||||
|
||||
Select a project or create a new project:
|
||||
‣ ${{ github.event.repository.name }}-6783521
|
||||
```
|
||||
3. Update your kubeconfig: `uffizzi cluster update-kubeconfig pr-${{ needs.cache-manifests-file.outputs.pr-number }} --kubeconfig=[PATH_TO_KUBECONFIG]`
|
||||
After updating your kubeconfig, you can manage your cluster with `kubectl`, `kustomize`, `helm`, and other tools that use kubeconfig files: `kubectl get namespace --kubeconfig [PATH_TO_KUBECONFIG]`
|
||||
|
||||
|
||||
Access the `backstage` endpoint at [`https://${{ steps.prev.outputs.backstage_url }}`](https://${{ steps.prev.outputs.backstage_url }})
|
||||
|
||||
edit-mode: replace
|
||||
|
||||
delete-uffizzi-preview:
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
id-token: write
|
||||
name: Delete the Uffizzi Virtual Cluster
|
||||
needs:
|
||||
- cache-manifests-file
|
||||
if: ${{ needs.cache-manifests-file.outputs.action == 'closed' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||
|
||||
- name: Delete Virtual Cluster
|
||||
uses: UffizziCloud/cluster-action@main
|
||||
with:
|
||||
cluster-name: pr-${{ needs.cache-manifests-file.outputs.pr-number }}
|
||||
server: https://app.uffizzi.com
|
||||
action: delete
|
||||
|
||||
# Identify comment to be updated
|
||||
- name: Find comment for Ephemeral Environment
|
||||
uses: peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e # v3
|
||||
id: find-comment
|
||||
with:
|
||||
issue-number: ${{ needs.cache-manifests-file.outputs.pr-number }}
|
||||
comment-author: 'github-actions[bot]'
|
||||
body-includes: pr-${{ needs.cache-manifests-file.outputs.pr-number }}
|
||||
direction: last
|
||||
|
||||
- name: Update Comment with Deletion
|
||||
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4
|
||||
with:
|
||||
comment-id: ${{ steps.find-comment.outputs.comment-id }}
|
||||
issue-number: ${{ needs.cache-manifests-file.outputs.pr-number }}
|
||||
body: |
|
||||
Uffizzi Cluster `pr-${{ needs.cache-manifests-file.outputs.pr-number }}` was deleted.
|
||||
edit-mode: replace
|
||||
@@ -10,7 +10,6 @@
|
||||

|
||||
[](https://codecov.io/gh/backstage/backstage)
|
||||
[](https://github.com/backstage/backstage/releases)
|
||||
[](https://app.uffizzi.com/ephemeral-environments/backstage/backstage)
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/7678)
|
||||
[](https://securityscorecards.dev/viewer/?uri=github.com/backstage/backstage)
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||

|
||||
[](https://codecov.io/gh/backstage/backstage)
|
||||
[](https://github.com/backstage/backstage/releases)
|
||||
[](https://app.uffizzi.com/ephemeral-environments/backstage/backstage)
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/7678)
|
||||
[](https://securityscorecards.dev/viewer/?uri=github.com/backstage/backstage)
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ English \| [한국어](README-ko_kr.md) \| [中文版](README-zh_Hans.md)
|
||||

|
||||
[](https://codecov.io/gh/backstage/backstage)
|
||||
[](https://github.com/backstage/backstage/releases)
|
||||
[](https://app.uffizzi.com/ephemeral-environments/backstage/backstage)
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/7678)
|
||||
[](https://securityscorecards.dev/viewer/?uri=github.com/backstage/backstage)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user