Check changes automatically
When you change a project, you usually want to know whether it still works. You might run tests, check formatting or build the application. Continuous integration, usually called CI, runs those checks automatically when code changes.
On Pillion, a workflow is a file describing that automatic work. A run is one execution of the workflow. Each run contains jobs, which contain ordered steps. A runner is the computer that executes a job.
You can use Git and pull requests without writing a workflow. Add one when there is a repeatable check you want every change to pass.
Add your first workflow
This example checks that your repository contains a non-empty README. Start with a repository containing README.md, such as the one from Your first repository.
- In your local repository, create a new branch for the change.
- Create a folder called
.pillionat the top level of the repository, then a folder calledworkflowsinside it. - Create
ci.ymlinside that folder and paste the following text. YAML uses indentation to group settings, so keep the spaces as shown.
name: CI
on: [push, pull_request]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check the README
run: test -s README.mdnamelabels the workflow.onselects the events that start it: pushes and pull requests.checkis the name of this job.runs-onasks for a runner matching the Linux labelubuntu-latest.- The
usesstep runs a reusable action. Checkout makes your repository’s files available on the runner. - The
runstep executes a shell command.test -s README.mdsucceeds if the file exists and has content; otherwise it fails.
Save the file, then commit and push it:
git add .pillion/workflows/ci.yml
git commit -m "Check that the README is present"
git push -u origin YOUR-BRANCHReplace YOUR-BRANCH with your branch name. If you use an HTTPS token, it needs Workflows: write as well as Contents: write to push workflow files. Create a token with those permissions in Access tokens if needed.
Open the repository’s Runs page. You should see CI, its check job and the README step. Merge the workflow through a pull request to make it part of the default branch. Pull-request events read the workflow from the base branch, so its push run is the first check to look for while you are adding it.
This example only checks the README. Add your project’s install, test and build commands as further steps, using a runner with the tools they need.
Read a run and understand a failure
Open a run, select its job and inspect the steps. A log is the text a step printed while running. Start with the failed step’s first useful error: a later error may simply be a consequence of it.
- Queued: the job is waiting for a matching runner. Check runner availability, labels and, for hosted jobs, the owner’s minutes and plan.
- In progress: the job is still executing. Read its current log for progress.
- Failed: a step or the job could not complete successfully. Correct the file or setting, commit and push again.
- Waiting for approval: a deployment needs an authorized person to allow it to continue.
- No run: check the workflow’s event, branch filters and directory. A malformed file is reported as an Invalid workflow file job.
A successful run means the checks you defined passed. Choose checks that exercise the behaviour your project needs, and continue to review changes yourself.
Choose where jobs run
A hosted runner uses compute provided by Pillion. An attached runner is a machine you operate, useful for special tools or access to your own network. The runs-on labels select a matching runner; attached runners with matching labels can take precedence over the hosted pool.
Start with the hosted Linux pool if it fits your project. See Pricing for availability and allowances. To use your own machine, follow the registration instructions below after the basic workflow is working.
Use credentials without committing them
A secret is a saved sensitive value, such as a deployment token, that a job needs. Add it in repository or organization Settings → Secrets. Give it a name, then refer to that name in the workflow. For a project that already has a deployment script, a step can look like this:
- name: Deploy
env:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
run: ./scripts/deploy.shenv supplies the secret to the script as an environment variable. Keep the actual value out of Git and avoid printing it: masking cannot recognise every encoded or transformed value.
A deployment delivers a version of your project to a destination such as a staging website. A deployment environment groups that destination’s secrets and approval requirements. It is separate from publishing a release for people to download.
Reference: workflow locations and GitHub migration
Pillion reads .yml and .yaml files in .pillion/workflows. If that directory contains no workflow files, it falls back to .github/workflows. It does not combine the directories.
If you are bringing workflows from GitHub, move all the ones you want to run together. Adding the first file under .pillion/workflows stops the fallback to the GitHub directory.
Reference: supported workflow features
Pillion supports push, pull_request and workflow_dispatch triggers; shell steps; composite and JavaScript actions; job dependencies; simple matrices; secrets; artifacts; and repository-scoped caches. An artifact is output saved for download; a cache reuses files to speed up later jobs. Actions resolve on the Pillion host first, with a GitHub fallback.
GitHub compatibility is a subset. Scheduled workflows, pull_request_target, Docker actions, reusable workflows and job OIDC are not supported. A step’s working-directory key is not supported; change directory inside its run script instead. Workflow permission settings support package permissions, not the full GitHub catalog.
Jobs receive a scoped GITHUB_TOKEN for supported repository API operations. Fork pull requests receive a read-only token and no repository secrets. They run only on hosted compute; if that compute is unavailable, the run reports that action is required.
Reference: attach your own runner
Obtain the Pillion forge-runner binary for your machine. Open repository or organization Settings → Runners and select Issue registration token. In a dedicated directory on the runner machine, run:
FORGE_RUNNER_URL=https://pillion.dev forge-runner configure --token 'REGISTRATION_TOKEN'
forge-runner runReplace the host and token with your service URL and registration token. Registration tokens are single-use and expire after one hour. Configuration saves the runner credential in .runner; keep that file private.
Keep the process running under the machine’s service manager, using the same working directory after restarts. Target the runner’s labels in the workflow, for example runs-on: [self-hosted, macos]. Attached runners execute jobs directly on your machine, so use them for code you trust.