1name: CI # label shown in the Actions tab
2run-name: CI for ${{ github.ref_name }} # optional: title of each run
3
4on: # WHEN to run
5 push: # on every push...
6 branches: [main] # ...but only to main
7 pull_request: # on PRs...
8 branches: [main] # ...that target main
9 workflow_dispatch: # adds a manual "Run workflow" button
10
11permissions: # least-privilege GITHUB_TOKEN
12 contents: read # only read the repo
13
14concurrency: # one run per branch at a time
15 group: ${{ github.workflow }}-${{ github.ref }}
16 cancel-in-progress: true # new push cancels the old run
17
18env: # variables for ALL jobs/steps
19 NODE_VERSION: '22'
20
21jobs: # WHAT to run
22 test: # job id (your choice, used by needs:)
23 name: Lint & test # display name
24 runs-on: ubuntu-latest # fresh GitHub-hosted Linux VM
25 timeout-minutes: 15 # kill it if it hangs (default 360)
26 steps: # executed top to bottom
27 - name: Checkout # step label in the log
28 uses: actions/checkout@v7 # action: clone the repo into the runner
29
30 - name: Setup Node
31 uses: actions/setup-node@v7 # action: install Node
32 with: # inputs for the action
33 node-version: ${{ env.NODE_VERSION }} # expression reads env
34 cache: npm # cache ~/.npm keyed on package-lock.json
35
36 - name: Install
37 run: npm ci # shell command (bash on Linux)
38
39 - name: Lint
40 run: npm run lint
41
42 - name: Test
43 run: npm test -- --coverage
44 env: # env only for this step
45 CI: true