Skip to content

The Three Demo Workflows

These are the complete, working definitions behind the demo's Self-service portal. Paste each into the workflow editor's JSON tab (or POST /api/v1/workflows) and adapt org/repo/project ids to your own.

1. Deploy Stack (GitHub Actions)

A rolling deployment: three GitHub repositories deployed in sequence (orders → payments → frontend), then the result recorded as a deployment entity — the recording step runs ALWAYS, so failures are recorded too.

json
{
  "identifier": "deploy-stack-github",
  "title": "Deploy Stack (GitHub Actions)",
  "icon": "LucideGithub",
  "description": "Rolling deployment of the order stack: orders-service, then payments-service, then frontend-webapp — each via GitHub Actions in its own repository. Records a deployment entity.",
  "kind": "WORKFLOW",
  "trigger": {
    "type": "self-service",
    "operation": "CREATE",
    "userInputs": {
      "required": ["environment", "version"],
      "properties": {
        "version": { "type": "string", "title": "Version", "default": "1.0.0" },
        "environment": {
          "enum": ["dev", "staging", "prod"],
          "type": "string",
          "title": "Environment",
          "default": "staging"
        }
      }
    },
    "blueprintIdentifier": "deployment"
  },
  "published": true,
  "steps": [
    {
      "identifier": "deploy_orders",
      "title": "Deploy orders-service (GitHub)",
      "order": 0,
      "type": "GITHUB",
      "config": {
        "org": "idpnextdemo",
        "ref": "main",
        "repo": "orders-service",
        "workflow": "deploy.yml",
        "workflowInputs": {
          "version": "{{ .inputs.version }}",
          "environment": "{{ .inputs.environment }}"
        }
      },
      "dependsOn": [],
      "condition": "ON_SUCCESS",
      "timeoutMinutes": 10
    },
    {
      "identifier": "deploy_payments",
      "title": "Deploy payments-service (GitHub)",
      "order": 1,
      "type": "GITHUB",
      "config": {
        "org": "idpnextdemo",
        "ref": "main",
        "repo": "payments-service",
        "workflow": "deploy.yml",
        "workflowInputs": {
          "version": "{{ .inputs.version }}",
          "environment": "{{ .inputs.environment }}"
        }
      },
      "dependsOn": ["deploy_orders"],
      "condition": "ON_SUCCESS",
      "timeoutMinutes": 10
    },
    {
      "identifier": "deploy_frontend",
      "title": "Deploy frontend-webapp (GitHub)",
      "order": 2,
      "type": "GITHUB",
      "config": {
        "org": "idpnextdemo",
        "ref": "main",
        "repo": "frontend-webapp",
        "workflow": "deploy.yml",
        "workflowInputs": {
          "version": "{{ .inputs.version }}",
          "environment": "{{ .inputs.environment }}"
        }
      },
      "dependsOn": ["deploy_orders", "deploy_payments"],
      "condition": "ON_SUCCESS",
      "timeoutMinutes": 10
    },
    {
      "identifier": "record",
      "title": "Record deployment",
      "order": 3,
      "type": "UPSERT_ENTITY",
      "config": {
        "mapping": {
          "title": "Deploy {{ .inputs.version }} to {{ .inputs.environment }} (GitHub)",
          "identifier": "{{ .run.id }}",
          "properties": {
            "url": "https://idpnext.wazyneo.com/self-service/runs/{{ .run.id }}",
            "status": "{{ .steps.deploy_frontend.status }}",
            "version": "{{ .inputs.version }}",
            "provider": "github",
            "services": ["orders-service", "payments-service", "frontend-webapp"],
            "workflow": "Deploy Stack (GitHub Actions)",
            "environment": "{{ .inputs.environment }}",
            "triggeredBy": "{{ .user.email }}"
          }
        },
        "blueprintIdentifier": "deployment"
      },
      "dependsOn": ["deploy_frontend"],
      "condition": "ALWAYS",
      "timeoutMinutes": 10
    }
  ]
}

Points to notice:

  • Each GITHUB step targets the deploy.yml from Part 3 and forwards the two user inputs. The IDP adds port_run_id automatically.
  • record depends on the last deploy but has "condition": "ALWAYS" — the Deployments page shows failed deployments too, with status taken from {{ .steps.deploy_frontend.status }}.

2. Deploy Stack (GitLab CI)

Same idea with GitLab: analytics first, then orders and payments in parallel (both depend only on deploy_analytics). The recorded status is computed with a jq conditional over both parallel steps.

json
{
  "identifier": "deploy-stack-gitlab",
  "title": "Deploy Stack (GitLab CI)",
  "icon": "LucideGitBranch",
  "description": "Deploys analytics-pipeline first, then orders-service and payments-service in parallel — each via a GitLab CI pipeline in its own project. Records a deployment entity.",
  "kind": "WORKFLOW",
  "trigger": {
    "type": "self-service",
    "operation": "CREATE",
    "userInputs": {
      "required": ["environment", "version"],
      "properties": {
        "version": { "type": "string", "title": "Version", "default": "1.0.0" },
        "environment": {
          "enum": ["dev", "staging", "prod"],
          "type": "string",
          "title": "Environment",
          "default": "staging"
        }
      }
    },
    "blueprintIdentifier": "deployment"
  },
  "published": true,
  "steps": [
    {
      "identifier": "deploy_analytics",
      "title": "Deploy analytics-pipeline (GitLab)",
      "order": 0,
      "type": "GITLAB",
      "config": {
        "ref": "main",
        "projectId": 84432928,
        "pipelineVariables": {
          "DEPLOY_ENV": "{{ .inputs.environment }}",
          "DEPLOY_VERSION": "{{ .inputs.version }}"
        }
      },
      "dependsOn": [],
      "condition": "ON_SUCCESS",
      "timeoutMinutes": 10
    },
    {
      "identifier": "deploy_orders",
      "title": "Deploy orders-service (GitLab)",
      "order": 1,
      "type": "GITLAB",
      "config": {
        "ref": "main",
        "projectId": 84432919,
        "pipelineVariables": {
          "DEPLOY_ENV": "{{ .inputs.environment }}",
          "DEPLOY_VERSION": "{{ .inputs.version }}"
        }
      },
      "dependsOn": ["deploy_analytics"],
      "condition": "ON_SUCCESS",
      "timeoutMinutes": 10
    },
    {
      "identifier": "deploy_payments",
      "title": "Deploy payments-service (GitLab)",
      "order": 2,
      "type": "GITLAB",
      "config": {
        "ref": "main",
        "projectId": 84432915,
        "pipelineVariables": {
          "DEPLOY_ENV": "{{ .inputs.environment }}",
          "DEPLOY_VERSION": "{{ .inputs.version }}"
        }
      },
      "dependsOn": ["deploy_analytics"],
      "condition": "ON_SUCCESS",
      "timeoutMinutes": 10
    },
    {
      "identifier": "record",
      "title": "Record deployment",
      "order": 3,
      "type": "UPSERT_ENTITY",
      "config": {
        "mapping": {
          "title": "Deploy {{ .inputs.version }} to {{ .inputs.environment }} (GitLab)",
          "identifier": "{{ .run.id }}",
          "properties": {
            "url": "https://idpnext.wazyneo.com/self-service/runs/{{ .run.id }}",
            "status": "{{ if (.steps.deploy_orders.status == \"SUCCESS\") and (.steps.deploy_payments.status == \"SUCCESS\") then \"SUCCESS\" else \"FAILURE\" end }}",
            "version": "{{ .inputs.version }}",
            "provider": "gitlab",
            "services": ["analytics-pipeline", "orders-service", "payments-service"],
            "workflow": "Deploy Stack (GitLab CI)",
            "environment": "{{ .inputs.environment }}",
            "triggeredBy": "{{ .user.email }}"
          }
        },
        "blueprintIdentifier": "deployment"
      },
      "dependsOn": ["deploy_orders", "deploy_payments"],
      "condition": "ALWAYS",
      "timeoutMinutes": 10
    }
  ]
}

projectId is the numeric GitLab project id (Project → Settings → General, or GET /api/v4/groups/<group>/projects).

3. Full-Stack Release (GitHub + GitLab)

The governance showcase: an approval gate, then a GitHub deployment, then a GitLab deployment, then recording. The GitHub step authenticates with a stored secret instead of the server environment.

json
{
  "identifier": "release-full-stack",
  "title": "Full-Stack Release (GitHub + GitLab)",
  "icon": "LucideRocket",
  "description": "Approval-gated release: deploys the backend via GitHub Actions (orders-service), then the frontend via a GitLab CI pipeline (frontend-webapp). Records a deployment entity.",
  "kind": "WORKFLOW",
  "trigger": {
    "type": "self-service",
    "operation": "CREATE",
    "userInputs": {
      "required": ["environment", "version"],
      "properties": {
        "version": { "type": "string", "title": "Version", "default": "1.0.0" },
        "environment": {
          "enum": ["dev", "staging", "prod"],
          "type": "string",
          "title": "Environment",
          "default": "prod"
        }
      }
    },
    "blueprintIdentifier": "deployment"
  },
  "published": true,
  "steps": [
    {
      "identifier": "approve",
      "title": "Release approval",
      "order": 0,
      "type": "APPROVAL",
      "config": {
        "approvers": [],
        "onTimeout": "approve",
        "timeoutMinutes": 5
      },
      "dependsOn": [],
      "condition": "ON_SUCCESS",
      "timeoutMinutes": 5
    },
    {
      "identifier": "deploy_backend",
      "title": "Deploy orders-service backend (GitHub)",
      "order": 1,
      "type": "GITHUB",
      "config": {
        "org": "idpnextdemo",
        "ref": "main",
        "repo": "orders-service",
        "workflow": "deploy.yml",
        "credentials": {
          "source": "secret",
          "version": "latest",
          "secretIdentifier": "idpnetxdemo-github-app"
        },
        "workflowInputs": {
          "version": "{{ .inputs.version }}",
          "environment": "{{ .inputs.environment }}"
        }
      },
      "dependsOn": ["approve"],
      "condition": "ON_SUCCESS",
      "timeoutMinutes": 10
    },
    {
      "identifier": "deploy_frontend",
      "title": "Deploy frontend-webapp (GitLab)",
      "order": 2,
      "type": "GITLAB",
      "config": {
        "ref": "main",
        "projectId": 84432930,
        "pipelineVariables": {
          "DEPLOY_ENV": "{{ .inputs.environment }}",
          "DEPLOY_VERSION": "{{ .inputs.version }}"
        }
      },
      "dependsOn": ["deploy_backend"],
      "condition": "ON_SUCCESS",
      "timeoutMinutes": 10
    },
    {
      "identifier": "record",
      "title": "Record deployment",
      "order": 3,
      "type": "UPSERT_ENTITY",
      "config": {
        "mapping": {
          "title": "Release {{ .inputs.version }} to {{ .inputs.environment }} (Full stack)",
          "identifier": "{{ .run.id }}",
          "properties": {
            "url": "https://idpnext.wazyneo.com/self-service/runs/{{ .run.id }}",
            "status": "{{ .steps.deploy_frontend.status }}",
            "version": "{{ .inputs.version }}",
            "provider": "mixed",
            "services": ["orders-service", "frontend-webapp"],
            "workflow": "Full-Stack Release (GitHub + GitLab)",
            "environment": "{{ .inputs.environment }}",
            "triggeredBy": "{{ .user.email }}"
          }
        },
        "blueprintIdentifier": "deployment"
      },
      "dependsOn": ["deploy_frontend"],
      "condition": "ALWAYS",
      "timeoutMinutes": 10
    }
  ]
}

The APPROVAL step config:

  • approvers: [] — any user who can see the run may approve or decline. List user emails to restrict it.
  • onTimeout: "approve" + timeoutMinutes: 5 — if nobody decides within 5 minutes, the release auto-approves (demo-friendly; in production you'd typically use "reject").

Approvals need a human

Service accounts cannot approve APPROVAL steps ("Failed to record approval decision") — approvals must come from a real user, or from the onTimeout policy.

Next: secrets & step credentials →

IDP Next — Internal Developer Platform