Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New-feature, WiP: Ephemeral Environments for PRs — Uffizzi Integration #18127

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
183 changes: 183 additions & 0 deletions .github/workflows/uffizzi-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
name: Build PR Image
on:
pull_request:
types: [opened, synchronize, reopened, closed, review_requested]

jobs:
build-harbor-portal:
name: Build and push `Harbor Portal`
runs-on: ubuntu-latest
outputs:
tags: ${{ steps.meta.outputs.tags }}
if: ${{ github.event.action != 'closed' }}
steps:
- name: Checkout git repo
uses: actions/checkout@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

- name: Generate UUID image name
id: uuid
run: echo "UUID_WORKER=$(uuidgen)" >> $GITHUB_ENV

- name: Docker metadata
id: meta
uses: docker/metadata-action@v4
with:
images: registry.uffizzi.com/${{ env.UUID_WORKER }}
tags: |
type=raw,value=60d

- name: Build and Push Image to registry.uffizzi.com - Uffizzi's ephemeral Registry
uses: docker/build-push-action@v3
with:
context: .
build-args: |
harbor_base_image_version=v2.5.5
harbor_base_namespace=goharbor
file: ./uffizzi-previews/docker/Dockerfile.portal.uffizzi
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
push: true
cache-from: type=gha
cache-to: type=gha, mode=max

build-jobservice:
name: Build and push `Jobservice`
runs-on: ubuntu-latest
outputs:
tags: ${{ steps.meta.outputs.tags }}
if: ${{ github.event.action != 'closed' }}
steps:
- name: Checkout git repo
uses: actions/checkout@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

- name: Generate UUID image name
id: uuid
run: echo "UUID_WORKER=$(uuidgen)" >> $GITHUB_ENV

- name: Docker metadata
id: meta
uses: docker/metadata-action@v4
with:
images: registry.uffizzi.com/${{ env.UUID_WORKER }}
tags: |
type=raw,value=60d

- name: Build and Push Image to registry.uffizzi.com - Uffizzi's ephemeral Registry
uses: docker/build-push-action@v3
with:
context: .
build-args: |
harbor_base_image_version=v2.5.5
harbor_base_namespace=goharbor
file: ./uffizzi-previews/docker/Dockerfile.jobservice.uffizzi
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
push: true
cache-from: type=gha
cache-to: type=gha, mode=max

build-registry-ctl:
name: Build and push `Registry-ctl`
runs-on: ubuntu-latest
outputs:
tags: ${{ steps.meta.outputs.tags }}
if: ${{ github.event.action != 'closed' }}
steps:
- name: Checkout git repo
uses: actions/checkout@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

- name: Generate UUID image name
id: uuid
run: echo "UUID_WORKER=$(uuidgen)" >> $GITHUB_ENV

- name: Docker metadata
id: meta
uses: docker/metadata-action@v4
with:
images: registry.uffizzi.com/${{ env.UUID_WORKER }}
tags: |
type=raw,value=60d

- name: Build and Push Image to registry.uffizzi.com - Uffizzi's ephemeral Registry
uses: docker/build-push-action@v3
with:
context: .
build-args: |
harbor_base_image_version=v2.5.5
harbor_base_namespace=goharbor
file: ./uffizzi-previews/docker/Dockerfile.registryctl.uffizzi
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
push: true
cache-from: type=gha
cache-to: type=gha, mode=max

render-compose-file:
name: Render Docker Compose File
# Pass output of this workflow to another triggered by `workflow_run` event.
runs-on: ubuntu-latest
needs:
- build-harbor-portal
- build-registry-ctl
- build-jobservice
outputs:
compose-file-cache-key: ${{ steps.hash.outputs.hash }}
steps:
- name: Checkout git repo
uses: actions/checkout@v3
- name: Render Compose File
run: |
REGISTRY_CTL_IMAGE=${{needs.build-registry-ctl.outputs.tags}}
PORTAL_IMAGE=${{needs.build-harbor-portal.outputs.tags}}
JOBSERVICE_IMAGE=${{needs.build-jobservice.outputs.tags}}
export PORTAL_IMAGE REGISTRY_CTL_IMAGE JOBSERVICE_IMAGE
export UFFIZZI_URL=\$UFFIZZI_URL
# Render simple template from environment variables.
envsubst < ./uffizzi-previews/docker-compose.uffizzi.yml > docker-compose.rendered.yml
cat docker-compose.rendered.yml
- name: Upload Rendered Compose File as Artifact
uses: actions/upload-artifact@v3
with:
name: preview-spec
path: docker-compose.rendered.yml
retention-days: 2
- name: Serialize PR Event to File
run: |
cat << EOF > event.json
${{ toJSON(github.event) }}

EOF
- name: Upload PR Event as Artifact
uses: actions/upload-artifact@v3
with:
name: preview-spec
path: event.json
retention-days: 2

delete-preview:
name: Call for Preview Deletion
runs-on: ubuntu-latest
if: ${{ github.event.action == 'closed' }}
steps:
# If this PR is closing, we will not render a compose file nor pass it to the next workflow.
- name: Serialize PR Event to File
run: |
cat << EOF > event.json
${{ toJSON(github.event) }}

EOF
- name: Upload PR Event as Artifact
uses: actions/upload-artifact@v3
with:
name: preview-spec
path: event.json
retention-days: 2
89 changes: 89 additions & 0 deletions .github/workflows/uffizzi-preview.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
name: Deploy Uffizzi Preview

# Workflow run — runs only when the Build PR/ uffizzi-build.yml completes successfully.
on:
workflow_run:
workflows:
- "Build PR Image"
types:
- completed


jobs:
cache-compose-file:
name: Cache Compose File
if: ${{ github.event.workflow_run.conclusion == 'success' }}
runs-on: ubuntu-latest
outputs:
compose-file-cache-key: ${{ env.HASH }}
pr-number: ${{ env.PR_NUMBER }}
steps:
- name: 'Download artifacts'
# Fetch output (zip archive) from the workflow run that triggered this workflow.
uses: actions/github-script@v6
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];
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: 'Unzip artifact'
run: unzip preview-spec.zip
- name: Read Event into ENV
run: |
echo 'EVENT_JSON<<EOF' >> $GITHUB_ENV
cat event.json >> $GITHUB_ENV
echo 'EOF' >> $GITHUB_ENV

- name: Hash Rendered Compose File
id: hash
# If the previous workflow was triggered by a PR close event, we will not have a compose file artifact.
if: ${{ fromJSON(env.EVENT_JSON).action != 'closed' }}
run: echo "HASH=$(md5sum docker-compose.rendered.yml | awk '{ print $1 }')" >> $GITHUB_ENV
- name: Cache Rendered Compose File
if: ${{ fromJSON(env.EVENT_JSON).action != 'closed' }}
uses: actions/cache@v3
with:
path: docker-compose.rendered.yml
key: ${{ env.HASH }}

- name: Read PR Number From Event Object
id: pr
run: echo "PR_NUMBER=${{ fromJSON(env.EVENT_JSON).number }}" >> $GITHUB_ENV
- name: DEBUG - Print Job Outputs
if: ${{ runner.debug }}
run: |
echo "PR number: ${{ env.PR_NUMBER }}"
echo "Compose file hash: ${{ env.HASH }}"
cat event.json

deploy-uffizzi-preview:
name: Use Remote Workflow to Preview on Uffizzi
needs:
- cache-compose-file
if: ${{ github.event.workflow_run.conclusion == 'success' }}
uses: UffizziCloud/preview-action/.github/workflows/reusable.yaml@v2
with:
# If this workflow was triggered by a PR close event, cache-key will be an empty string
# and this reusable workflow will delete the preview deployment.
compose-file-cache-key: ${{ needs.cache-compose-file.outputs.compose-file-cache-key }}
compose-file-cache-path: docker-compose.rendered.yml
server: https://app.uffizzi.com
pr-number: ${{ needs.cache-compose-file.outputs.pr-number }}
permissions:
contents: read
pull-requests: write
id-token: write
1 change: 0 additions & 1 deletion make/migrations/postgresql/0001_initial_schema.up.sql
Original file line number Diff line number Diff line change
Expand Up @@ -364,4 +364,3 @@ CREATE TABLE IF NOT EXISTS alembic_version (
);

insert into alembic_version values ('1.6.0');

1 change: 0 additions & 1 deletion make/photon/portal/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,3 @@ STOPSIGNAL SIGQUIT
HEALTHCHECK CMD curl --fail -s http://localhost:8080 || curl -k --fail -s https://localhost:8443 || exit 1
USER nginx
CMD ["nginx", "-g", "daemon off;"]

6 changes: 6 additions & 0 deletions uffizzi-previews/config/core/app.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
appname = Harbor
runmode = dev
enablegzip = true

[dev]
httpport = 8080
41 changes: 41 additions & 0 deletions uffizzi-previews/config/jobservice/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
#Protocol used to serve
protocol: "http"

#Config certification if use 'https' protocol
#https_config:
# cert: "server.crt"
# key: "server.key"

#Server listening port
port: 8086

#Worker pool
worker_pool:
#Worker concurrency
workers: 10
backend: "redis"
#Additional config if use 'redis' backend
redis_pool:
#redis://[arbitrary_username:password@]ipaddress:port/database_index
redis_url: redis://localhost:6379/2
namespace: "harbor_job_service_namespace"
#Loggers for the running job
job_loggers:
- name: "STD_OUTPUT" # logger backend name, only support "FILE" and "STD_OUTPUT"
level: "INFO" # INFO/DEBUG/WARNING/ERROR/FATAL
- name: "FILE"
level: "INFO"
settings: # Customized settings of logger
base_dir: "/var/log/jobs"
sweeper:
duration: 1 #days
settings: # Customized settings of sweeper
work_dir: "/var/log/jobs"

#Loggers for the job service
loggers:
- name: "STD_OUTPUT" # Same with above
level: "INFO"
#Admin server endpoint
admin_server: "http://localhost:8080"
36 changes: 36 additions & 0 deletions uffizzi-previews/config/registry/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
version: 0.1
log:
level: info
fields:
service: registry
storage:
cache:
layerinfo: redis
filesystem:
rootdirectory: /storage
maintenance:
uploadpurging:
enabled: false
delete:
enabled: true
redis:
addr: localhost:6379
password:
db: 1
http:
addr: :5000
secret: password
debug:
addr: localhost:5001
auth:
htpasswd:
realm: harbor-registry-basic-realm
path: /etc/registry/passwd
notifications:
endpoints:
- name: harbor
disabled: false
url: http://localhost:8080/service/notifications
timeout: 3000ms
threshold: 5
backoff: 1s
9 changes: 9 additions & 0 deletions uffizzi-previews/config/registryctl/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
protocol: "http"
port: 8085
log_level: "INFO"
registry_config: "/etc/registry/config.yml"

#https_config:
# cert: "server.crt"
# key: "server.key"
Loading