> For the complete documentation index, see [llms.txt](https://docs.euno.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.euno.ai/sources/business-intelligence/cube-core-integration/github-actions-upload.md).

# GitHub Actions Upload

This workflow zips your Cube `model/` tree and uploads it to Euno after schema changes land in your repository.

## Prerequisites

* GitHub repository containing your Cube Core schema YAML under `model/`
* Euno **trigger secret** for your Cube Core source, stored as a GitHub secret

## Setup

### 1. Add GitHub Secrets

In your GitHub repository, add the following secrets (Settings → Secrets and variables → Actions):

* `EUNO_INTEGRATION_KEY`: Your Cube Core source **trigger secret** (Bearer token for uploads)
* `EUNO_ENDPOINT_URL`: Your Euno `prepare-upload` endpoint URL (for example, `https://api.app.euno.ai/accounts/YOUR_ACCOUNT_ID/integrations/YOUR_INTEGRATION_ID/prepare-upload`)

### 2. Create Workflow File

Create `.github/workflows/cube-core-euno-upload.yml` in your repository:

```yaml
name: Cube Core Upload to Euno

on:
  push:
    branches: [ main, master ]
    paths:
      - 'model/**'
  workflow_dispatch:

jobs:
  upload-cube-schema:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v4

    - name: Create and upload Cube model zip
      run: |
        set -euo pipefail

        if [ ! -d model ]; then
          echo "Error: model/ directory not found"
          exit 1
        fi

        shopt -s globstar nullglob
        yaml_files=(model/**/*.yml model/**/*.yaml)
        if [ ${#yaml_files[@]} -eq 0 ]; then
          echo "Error: no YAML files found under model/"
          exit 1
        fi

        echo "Creating zip file with Cube schema YAML..."
        zip -r cube-model.zip model/

        echo "Requesting signed upload URL from Euno..."
        prepare_response=$(curl -s -w "\n%{http_code}" \
          -X POST \
          -H "Authorization: Bearer ${{ secrets.EUNO_INTEGRATION_KEY }}" \
          -H "Content-Type: application/json" \
          -d '{"filename": "cube-model.zip"}' \
          "${{ secrets.EUNO_ENDPOINT_URL }}")

        prepare_status_code=$(echo "$prepare_response" | tail -n1)
        prepare_response_body=$(echo "$prepare_response" | head -n -1)

        echo "Prepare-upload status code: $prepare_status_code"

        if [ "$prepare_status_code" -ne 200 ]; then
          echo "Failed to get signed URL with status code: $prepare_status_code"
          echo "Response: $prepare_response_body"
          exit 1
        fi

        upload_url=$(echo "$prepare_response_body" | jq -r '.upload.url // empty')

        if [ -z "$upload_url" ] || [ "$upload_url" = "null" ]; then
          echo "Failed to extract upload URL from response"
          echo "Response: $prepare_response_body"
          exit 1
        fi

        echo "Signed URL obtained"

        echo "Uploading Cube model zip..."
        upload_response=$(curl -s -w "\n%{http_code}" \
          -X PUT \
          -H "Content-Type: application/zip" \
          --data-binary @cube-model.zip \
          "$upload_url")

        upload_status_code=$(echo "$upload_response" | tail -n1)
        upload_response_body=$(echo "$upload_response" | head -n -1)

        echo "Upload status code: $upload_status_code"

        if [ "$upload_status_code" -eq 200 ] || [ "$upload_status_code" -eq 201 ]; then
          echo "Cube model uploaded successfully"
        else
          echo "Upload failed with status code: $upload_status_code"
          echo "Response: $upload_response_body"
          exit 1
        fi

    - name: Upload zip on failure
      if: failure()
      uses: actions/upload-artifact@v4
      with:
        name: cube-model-zip
        path: cube-model.zip
        retention-days: 3
```

## Configuration Notes

### Model directory layout

Euno expects YAML files under `model/**/*.yml` or `model/**/*.yaml`. Upload the complete `model/` tree when your deployment has joins or views that reference cubes defined in other files.

### Path filters

The example workflow runs only when files under `model/` change. Remove the `paths` filter if you want every push to main to upload, or adjust it to match your repository layout.

### Required GitHub Secrets

* `EUNO_INTEGRATION_KEY` — your Cube Core source **trigger secret** (Bearer token)
* `EUNO_ENDPOINT_URL` — your Cube Core source `prepare-upload` endpoint URL

## Workflow Triggers

The workflow runs on:

* **Push to main/master** when `model/**` changes
* **Manual trigger** — use the **Actions** tab to run on demand

## Related guides

* [Cube Core integration setup](/sources/business-intelligence/cube-core-integration.md)
* [Python Upload for Zip Artifacts](/sources/zip-artifact-python-upload.md) — standalone script using the same `prepare-upload` flow


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.euno.ai/sources/business-intelligence/cube-core-integration/github-actions-upload.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
