From 77437c90bbba40569a76b76f788a77a5aaca1a05 Mon Sep 17 00:00:00 2001 From: Dragos Gheorghioiu Date: Fri, 10 Jul 2026 17:12:15 +0300 Subject: [PATCH] feat: Automatic deployment Signed-off-by: Dragos Gheorghioiu --- .github/actions/setup-kraftkit/action.yaml | 26 +++++ .github/actions/setup-www/action.yaml | 117 +++++++++++++++++++++ .github/workflows/main.yaml | 86 +++++++++++++++ .gitignore | 1 + Kraftfile | 7 ++ 5 files changed, 237 insertions(+) create mode 100644 .github/actions/setup-kraftkit/action.yaml create mode 100644 .github/actions/setup-www/action.yaml create mode 100644 .github/workflows/main.yaml create mode 100644 Kraftfile diff --git a/.github/actions/setup-kraftkit/action.yaml b/.github/actions/setup-kraftkit/action.yaml new file mode 100644 index 00000000..f4872f85 --- /dev/null +++ b/.github/actions/setup-kraftkit/action.yaml @@ -0,0 +1,26 @@ +name: setup-kraftkit + +description: Setup KraftKit. + +inputs: + version: + description: KraftKit version to install (use latest to auto-detect). + required: false + default: latest + +runs: + using: composite + steps: + - name: Install + shell: bash + run: | + if [[ -z $(command -v kraft) ]]; then + _VERSION="${{ inputs.version }}" + if [[ -z "${_VERSION}" || "${_VERSION}" == "latest" ]]; then + _VERSION=$(curl -fsSL https://get.kraftkit.sh/latest.txt) + fi + wget -nv -LO kraft.tar.gz https://github.com/unikraft/kraftkit/releases/download/v${_VERSION}/kraft_${_VERSION}_linux_amd64.tar.gz; + tar xzf kraft.tar.gz kraft; + sudo mv kraft /usr/bin/; + rm kraft.tar.gz; + fi diff --git a/.github/actions/setup-www/action.yaml b/.github/actions/setup-www/action.yaml new file mode 100644 index 00000000..776b9cb8 --- /dev/null +++ b/.github/actions/setup-www/action.yaml @@ -0,0 +1,117 @@ +name: setup-www + +description: | + Deploys the Unikraft OSS documentation site (oss-www). + +inputs: + environment: + required: true + description: The environment to use. + name: + required: true + description: Name of the service. + domain: + required: false + description: The domain to use for the deployment. + metro: + required: false + description: Unikraft Cloud Metro. + default: http://api.dal2.unikraft.cloud/v1 + memory: + required: false + description: Set the memory size. + default: 1536Mi + args: + required: false + description: Optional arguments you pass to kraft cloud deploy. + port: + required: false + description: The port the service listens on. + default: "3000" + log-level: + required: false + default: error + description: Set the logging level. + +outputs: + domain: + description: | + Either the input domain if set or the automatically generated value + otherwise. + value: ${{ steps.service.outputs.domain }} + +runs: + using: composite + steps: + - name: Create Deployment + uses: bobheadxi/deployments@v1 + id: init-deploy + with: + step: start + token: ${{ github.token }} + env: ${{ inputs.environment }} + + - name: Create Service Group + id: service + shell: bash + run: | + set -e; + + # Create the service if it does not exist. + _SVC=$(kraft cloud --metro "${{ inputs.metro }}" service get "${{ inputs.name }}" -o raw | jq -r '.data.service_groups[].error') + if [[ "${_SVC}" == "8" ]]; then + if [[ "${{ inputs.domain }}" == "" ]]; then + kraft cloud --metro "${{ inputs.metro }}" service create \ + --subdomain "${{ inputs.name }}" \ + --name "${{ inputs.name }}" \ + "443:${{ inputs.port }}" \ + ; + else + kraft cloud --metro "${{ inputs.metro }}" service create \ + --domain "${{ inputs.domain }}" \ + --name "${{ inputs.name }}" \ + "443:${{ inputs.port }}" \ + ; + fi + fi + + # Save the generated domain as an output variable + echo "domain=$(kraft cloud --metro ${{ inputs.metro }} service get ${{ inputs.name }} -o raw | jq -r '.data.service_groups[0].domains[0].fqdn')" >> $GITHUB_OUTPUT + + - name: Deploy + id: deploy + shell: bash + run: | + kraft cloud deploy \ + --rollout remove \ + --rollout-qualifier all \ + --memory "${{ inputs.memory }}" \ + --service "${{ inputs.name }}" \ + --image "${{ inputs.name }}" \ + --as kraftfile-runtime \ + ${{ inputs.args }} \ + .; + + - name: Test liveliness + id: liveliness + continue-on-error: true + shell: bash + run: | + sleep 15; + curl -Lk --fail "https://${{ steps.service.outputs.domain }}/" + + - name: Dump instance logs on failure + if: ${{ steps.liveliness.outcome == 'failure' }} + shell: bash + run: | + kraft cloud service logs "${{ inputs.name }}" + exit 1 + + - name: Update Deployment + uses: bobheadxi/deployments@v1 + with: + step: finish + token: ${{ github.token }} + env: ${{ inputs.environment }} + deployment_id: ${{ steps.init-deploy.outputs.deployment_id }} + status: ${{ job.status }} diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml new file mode 100644 index 00000000..d0709747 --- /dev/null +++ b/.github/workflows/main.yaml @@ -0,0 +1,86 @@ +name: main + +on: + push: + branches: [main] + paths: + - '**' + - '!.github/workflows/**/*' + - '.github/workflows/main.yaml' + - '!README.md' + +env: + UKC_TOKEN: ${{ secrets.UKC_TOKEN }} + UKC_METRO: ${{ secrets.UKC_METRO }} + KRAFTKIT_LOG_LEVEL: debug + KRAFTKIT_NO_CHECK_UPDATES: "true" + +permissions: + deployments: write + contents: read + +jobs: + deploy: + environment: + name: main + url: https://unikraft.org + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Validate required secrets + shell: bash + run: | + if [[ -z "${{ secrets.UKC_METRO }}" ]]; then + echo "Missing UKC_METRO secret" >&2 + exit 1 + fi + + - name: Setup KraftKit + uses: ./.github/actions/setup-kraftkit + + - name: Setup OSS docs website + id: www + uses: ./.github/actions/setup-www + continue-on-error: true + with: + environment: main + name: oss-www + domain: unikraft.org + metro: ${{ secrets.UKC_METRO }} + log-level: trace + + - uses: chrnorm/deployment-action@v2 + name: Create GitHub deployment + if: always() + id: deploy-github + with: + token: '${{ github.token }}' + environment-url: 'https://${{ steps.www.outputs.domain }}' + environment: main + + - name: Update deployment status (success) + if: ${{ steps.www.outcome == 'success' }} + uses: chrnorm/deployment-status@v2 + with: + token: '${{ github.token }}' + environment-url: 'https://${{ steps.www.outputs.domain }}' + deployment-id: '${{ steps.deploy-github.outputs.deployment_id }}' + state: 'success' + + - name: Update deployment status (failure) + if: ${{ steps.www.outcome == 'failure' }} + uses: chrnorm/deployment-status@v2 + with: + token: '${{ github.token }}' + environment-url: 'https://${{ steps.www.outputs.domain }}' + deployment-id: '${{ steps.deploy-github.outputs.deployment_id }}' + state: 'failure' + + - name: Fail job if deploy failed + if: ${{ steps.www.outcome == 'failure' }} + shell: bash + run: | + exit 1 diff --git a/.gitignore b/.gitignore index 403b6389..5c0c0283 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules .contentlayer .next +configs/search-meta.json diff --git a/Kraftfile b/Kraftfile new file mode 100644 index 00000000..3fa4d99d --- /dev/null +++ b/Kraftfile @@ -0,0 +1,7 @@ +spec: v0.6 + +runtime: base-compat:latest + +rootfs: ./Dockerfile + +cmd: ["node", "docs/server.js"]