events¶
One script for pushes, tags, pull requests, a nightly schedule and manual runs.
One script for every reason a run starts.
Amber steps have effects outside the run, so a pass is never reused. Pause it, or step through it, with the controls.
# One script for every reason a run starts.
#
# ctx.event says why: "push", "tag", "pull_request", "schedule" or "manual".
# The script answers with the steps for that reason. There is no separate
# list of triggers to keep in step with it; the one thing that has to be
# declared is a schedule, because nothing causes one.
schedule("nightly", cron = "0 3 * * *")
IMAGE = "node:22-bookworm-slim"
def node(name, command, **kwargs):
return step(name, image = IMAGE, run = "npm ci && " + command, **kwargs)
def ci(ctx):
lint = node("lint", "npm run lint")
test = node("test", "npm test")
checks = [lint, test]
# The slow suite, and an audit against a database that changes daily:
# once a night rather than on every push.
if ctx.event == "schedule" and ctx.schedule == "nightly":
return checks + [
node("end to end", "npm run test:e2e", needs = checks),
node("audit", "npm audit --audit-level=high", cache = False),
]
# A tag is a release.
if ctx.event == "tag":
return checks + [node("publish", "npm publish", needs = checks, cache = False)]
# A pull request gets a preview to look at. Not from a fork: that would
# be running a stranger's code with this repository's credentials.
if ctx.event == "pull_request" and not ctx.pr.fork:
return checks + [node("preview", "npm run deploy:preview", needs = checks, cache = False)]
# Pushes to main deploy to staging.
if ctx.event == "push" and ctx.ref == "main":
return checks + [node("deploy staging", "npm run deploy:staging", needs = checks, cache = False)]
return checks
# Generated by `starci compile` from events.ci.star. Edit that, not this.
#
# Each job is one step of the plan: the same image, command, tools and
# packages, given only the step's inputs. A job skips its work when it has
# already passed with the same inputs.
#
# What does not carry over:
# - The script looks at the pull request. Whether it comes from a fork carries
# over; any other rule about it does not, and every pull request is treated
# as one into main.
# - The script looks at the branch. Whether it is main carries over; any other
# rule about branch names does not, and every other branch is treated alike.
# - A schedule's runs may overlap here, where starci would skip a firing while
# the last run is still going; and a missed firing is never made up.
# - Passes are remembered in this repository's Actions cache, which GitHub
# scopes by branch and evicts when old. starci's own store has neither
# limit.
name: CI
on:
push:
branches: ['**']
tags: ['**']
pull_request:
schedule:
- cron: "0 3 * * *"
workflow_dispatch:
jobs:
lint:
name: "lint"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Has this already passed with these inputs?
id: passed
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/starci-passed
key: starci-passed-lint-d309b4ed71edb687-${{ hashFiles('**', '!.git/**') }}
- name: "lint"
if: steps.passed.outputs.cache-hit != 'true'
env:
STARCI_RUN: |-
npm ci && npm run lint
run: |
docker run --rm \
-v "$PWD:/workspace" \
-w /workspace \
node:22-bookworm-slim sh -c "$STARCI_RUN"
- name: Remember this pass
if: steps.passed.outputs.cache-hit != 'true'
run: mkdir -p "$RUNNER_TEMP/starci-passed" && date > "$RUNNER_TEMP/starci-passed/at"
test:
name: "test"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Has this already passed with these inputs?
id: passed
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/starci-passed
key: starci-passed-test-3dce010675ea0e57-${{ hashFiles('**', '!.git/**') }}
- name: "test"
if: steps.passed.outputs.cache-hit != 'true'
env:
STARCI_RUN: |-
npm ci && npm test
run: |
docker run --rm \
-v "$PWD:/workspace" \
-w /workspace \
node:22-bookworm-slim sh -c "$STARCI_RUN"
- name: Remember this pass
if: steps.passed.outputs.cache-hit != 'true'
run: mkdir -p "$RUNNER_TEMP/starci-passed" && date > "$RUNNER_TEMP/starci-passed/at"
deploy-staging:
name: "deploy staging"
runs-on: ubuntu-latest
needs: [lint, test]
if: ${{ (github.event_name == 'push' && github.ref == 'refs/heads/main') }}
steps:
- uses: actions/checkout@v4
- name: "deploy staging"
env:
STARCI_RUN: |-
npm ci && npm run deploy:staging
run: |
docker run --rm \
-v "$PWD:/workspace" \
-w /workspace \
node:22-bookworm-slim sh -c "$STARCI_RUN"
publish:
name: "publish"
runs-on: ubuntu-latest
needs: [lint, test]
if: ${{ (github.event_name == 'push' && github.ref_type == 'tag') }}
steps:
- uses: actions/checkout@v4
- name: "publish"
env:
STARCI_RUN: |-
npm ci && npm publish
run: |
docker run --rm \
-v "$PWD:/workspace" \
-w /workspace \
node:22-bookworm-slim sh -c "$STARCI_RUN"
preview:
name: "preview"
runs-on: ubuntu-latest
needs: [lint, test]
if: ${{ (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) }}
steps:
- uses: actions/checkout@v4
- name: "preview"
env:
STARCI_RUN: |-
npm ci && npm run deploy:preview
run: |
docker run --rm \
-v "$PWD:/workspace" \
-w /workspace \
node:22-bookworm-slim sh -c "$STARCI_RUN"
end-to-end:
name: "end to end"
runs-on: ubuntu-latest
needs: [lint, test]
if: ${{ (github.event_name == 'schedule' && github.event.schedule == '0 3 * * *') }}
steps:
- uses: actions/checkout@v4
- name: Has this already passed with these inputs?
id: passed
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/starci-passed
key: starci-passed-end-to-end-c35e8a3446283be5-${{ hashFiles('**', '!.git/**') }}
- name: "end to end"
if: steps.passed.outputs.cache-hit != 'true'
env:
STARCI_RUN: |-
npm ci && npm run test:e2e
run: |
docker run --rm \
-v "$PWD:/workspace" \
-w /workspace \
node:22-bookworm-slim sh -c "$STARCI_RUN"
- name: Remember this pass
if: steps.passed.outputs.cache-hit != 'true'
run: mkdir -p "$RUNNER_TEMP/starci-passed" && date > "$RUNNER_TEMP/starci-passed/at"
audit:
name: "audit"
runs-on: ubuntu-latest
if: ${{ (github.event_name == 'schedule' && github.event.schedule == '0 3 * * *') }}
steps:
- uses: actions/checkout@v4
- name: "audit"
env:
STARCI_RUN: |-
npm ci && npm audit --audit-level=high
run: |
docker run --rm \
-v "$PWD:/workspace" \
-w /workspace \
node:22-bookworm-slim sh -c "$STARCI_RUN"
# Generated by `starci compile --target circleci` from events.ci.star. Edit that, not this.
#
# Each job is one step of the plan: the same image, command, tools and
# packages, given only the step's inputs. A job skips its work when it has
# already passed with the same inputs.
#
# What does not carry over:
# - The script reads ctx.event, ctx.ref, so its plan depends on the commit.
# This file is the plan for a commit about which nothing is known, and is
# the same for every push: steps the script would add or drop for a
# particular branch or set of changed files are not represented.
# - Passes are remembered in this project's CircleCI cache, which expires.
# starci's own store does not.
version: 2.1
jobs:
lint:
machine:
image: ubuntu-2404:current
resource_class: medium
steps:
- checkout
- run:
name: "Identify the inputs"
command: |
git ls-files -s -- ':(top)' > /tmp/starci-inputs
- restore_cache:
name: Has this already passed with these inputs?
keys:
- starci-passed-lint-d309b4ed71edb687-{{ checksum "/tmp/starci-inputs" }}
- run:
name: "Stop here if it has"
command: |
if [ -e ~/starci-passed/at ]; then
echo "Passed before with the same inputs, on $(cat ~/starci-passed/at). Nothing to do."
circleci-agent step halt
fi
- run:
name: "lint"
environment:
STARCI_RUN: |-
npm ci && npm run lint
command: |
docker run --rm \
-v "$PWD:/workspace" \
-w /workspace \
node:22-bookworm-slim sh -c "$STARCI_RUN"
- run:
name: "Remember this pass"
command: |
mkdir -p ~/starci-passed && date > ~/starci-passed/at
- save_cache:
key: starci-passed-lint-d309b4ed71edb687-{{ checksum "/tmp/starci-inputs" }}
paths:
- ~/starci-passed
test:
machine:
image: ubuntu-2404:current
resource_class: medium
steps:
- checkout
- run:
name: "Identify the inputs"
command: |
git ls-files -s -- ':(top)' > /tmp/starci-inputs
- restore_cache:
name: Has this already passed with these inputs?
keys:
- starci-passed-test-3dce010675ea0e57-{{ checksum "/tmp/starci-inputs" }}
- run:
name: "Stop here if it has"
command: |
if [ -e ~/starci-passed/at ]; then
echo "Passed before with the same inputs, on $(cat ~/starci-passed/at). Nothing to do."
circleci-agent step halt
fi
- run:
name: "test"
environment:
STARCI_RUN: |-
npm ci && npm test
command: |
docker run --rm \
-v "$PWD:/workspace" \
-w /workspace \
node:22-bookworm-slim sh -c "$STARCI_RUN"
- run:
name: "Remember this pass"
command: |
mkdir -p ~/starci-passed && date > ~/starci-passed/at
- save_cache:
key: starci-passed-test-3dce010675ea0e57-{{ checksum "/tmp/starci-inputs" }}
paths:
- ~/starci-passed
workflows:
ci:
jobs:
- lint
- test
Download: events.ci.star, GitHub Actions, CircleCI