Skip to content

Commit e7080a9

Browse files
committed
Initial commit
0 parents  commit e7080a9

6 files changed

Lines changed: 310 additions & 0 deletions

File tree

.github/workflows/ci.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
8+
jobs:
9+
lint:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v4
13+
14+
- name: Lint shell scripts
15+
run: shellcheck install.sh run.sh
16+
17+
- name: Validate action.yml
18+
run: |
19+
npm install -g @action-validator/cli
20+
action-validator action.yml
21+
22+
test-install:
23+
strategy:
24+
matrix:
25+
os: [ubuntu-latest, macos-latest]
26+
runs-on: ${{ matrix.os }}
27+
steps:
28+
- uses: actions/checkout@v4
29+
30+
- name: Test CLI installation
31+
run: |
32+
bash install.sh
33+
./linear-release --version
34+
env:
35+
CLI_VERSION: latest
36+
RUNNER_OS: ${{ runner.os }}

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 Linear
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
<p align="center">
2+
<a href="https://linear.app" target="_blank" rel="noopener noreferrer">
3+
<img width="64" src="https://raw.githubusercontent.com/linear/linear/master/docs/logo.svg" alt="Linear logo">
4+
</a>
5+
</p>
6+
<h1 align="center">
7+
Linear Release Action
8+
</h1>
9+
<h3 align="center">
10+
GitHub Action for syncing deployments with Linear releases
11+
</h3>
12+
<p align="center">
13+
Connect your deployments to Linear releases.<br/>
14+
Automatically link issues to releases.
15+
</p>
16+
<p align="center">
17+
<a href="https://github.com/linear/linear-release-action/actions/workflows/ci.yml"><img src="https://github.com/linear/linear-release-action/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
18+
<a href="https://github.com/linear/linear-release-action/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="Linear Release Action is released under the MIT license."></a>
19+
</p>
20+
21+
> [!NOTE]
22+
> This project is currently in beta and requires enrollment to use. If you're interested in trying it out or need assistance, please contact [Linear support](https://linear.app/contact) or your account manager. APIs and commands may change in future releases.
23+
24+
## Overview
25+
26+
This action wraps the [Linear Release CLI](https://github.com/linear/linear-release) to integrate your CI/CD pipeline with [Linear's release management](https://linear.app/docs/releases). It automatically scans commits for Linear issue identifiers, detects pull request references, and creates or updates releases in Linear.
27+
28+
## Quick Start
29+
30+
```yaml
31+
permissions:
32+
contents: read
33+
34+
steps:
35+
- uses: actions/checkout@v4
36+
with:
37+
fetch-depth: 0 # Required for commit history
38+
39+
- uses: linear/linear-release-action@v0.1.0
40+
with:
41+
access_key: ${{ secrets.LINEAR_ACCESS_KEY }}
42+
```
43+
44+
## Inputs
45+
46+
| Input | Required | Default | Description |
47+
| --- | --- | --- | --- |
48+
| `access_key` | Yes | | Linear pipeline access key for authentication |
49+
| `command` | No | `sync` | Command to run: `sync`, `complete`, or `update` |
50+
| `name` | No | | Custom release name (only used with `sync` command) |
51+
| `version` | No | | Release version identifier |
52+
| `stage` | No | | Deployment stage such as `staging` or `production` (required for `update`) |
53+
| `include_paths` | No | | Filter commits by file paths (comma-separated globs for monorepos) |
54+
| `cli_version` | No | `latest` | Linear Release CLI version tag to install |
55+
56+
## Commands
57+
58+
### sync
59+
60+
Creates or updates a release by scanning commits for Linear issue identifiers.
61+
62+
```yaml
63+
- uses: linear/linear-release-action@v0.1.0
64+
with:
65+
access_key: ${{ secrets.LINEAR_ACCESS_KEY }}
66+
```
67+
68+
### complete
69+
70+
Marks the current release as complete.
71+
72+
```yaml
73+
- uses: linear/linear-release-action@v0.1.0
74+
with:
75+
access_key: ${{ secrets.LINEAR_ACCESS_KEY }}
76+
command: complete
77+
```
78+
79+
### update
80+
81+
Updates the deployment stage of the current release.
82+
83+
```yaml
84+
- uses: linear/linear-release-action@v0.1.0
85+
with:
86+
access_key: ${{ secrets.LINEAR_ACCESS_KEY }}
87+
command: update
88+
stage: staging
89+
```
90+
91+
### Monorepo filtering
92+
93+
Filter commits by file paths to track releases for specific packages:
94+
95+
```yaml
96+
- uses: linear/linear-release-action@v0.1.0
97+
with:
98+
access_key: ${{ secrets.LINEAR_ACCESS_KEY }}
99+
include_paths: apps/web/**,packages/shared/**
100+
```
101+
102+
## Troubleshooting
103+
104+
**"Unsupported OS" or "Unsupported arch" error**
105+
106+
The action only supports Linux x86_64 and macOS x86_64/arm64 runners. Windows is not supported.
107+
108+
**"access_key input is required" error**
109+
110+
Ensure you've set the `access_key` input with your Linear pipeline access key stored in GitHub Secrets.
111+
112+
**Issues not being linked**
113+
114+
Make sure your commits contain Linear issue identifiers (e.g., `ENG-123`) and that `actions/checkout` uses `fetch-depth: 0`.
115+
116+
## License
117+
118+
MIT - see [LICENSE](LICENSE)

action.yml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
name: linear-release-action
2+
description: Run Linear Release CLI to sync deployments with Linear releases
3+
author: Linear
4+
5+
branding:
6+
icon: tag
7+
color: blue
8+
9+
inputs:
10+
access_key:
11+
description: Linear pipeline access key for authentication. Store this in GitHub Secrets.
12+
required: true
13+
command:
14+
description: Command to run. Use "sync" to create/update a release, "complete" to mark it done, or "update" to change deployment stage.
15+
required: false
16+
default: sync
17+
name:
18+
description: Custom release name. Only used with the "sync" command.
19+
required: false
20+
version:
21+
description: Release version identifier (e.g., "v1.2.3").
22+
required: false
23+
stage:
24+
description: Deployment stage such as "staging" or "production". Required when command is "update".
25+
required: false
26+
include_paths:
27+
description: Filter commits by file paths using comma-separated globs (e.g., "apps/web/**,packages/**"). Useful for monorepos.
28+
required: false
29+
cli_version:
30+
description: Linear Release CLI version tag to install (e.g., "v0.1.0"). Defaults to latest.
31+
required: false
32+
default: latest
33+
34+
runs:
35+
using: composite
36+
steps:
37+
- name: Install Linear Release CLI
38+
shell: bash
39+
run: bash "${{ github.action_path }}/install.sh"
40+
env:
41+
CLI_VERSION: ${{ inputs.cli_version }}
42+
43+
- name: Run Linear Release
44+
shell: bash
45+
run: bash "${{ github.action_path }}/run.sh"
46+
env:
47+
LINEAR_ACCESS_KEY: ${{ inputs.access_key }}
48+
COMMAND: ${{ inputs.command }}
49+
INPUT_NAME: ${{ inputs.name }}
50+
INPUT_VERSION: ${{ inputs.version }}
51+
INPUT_STAGE: ${{ inputs.stage }}
52+
INPUT_INCLUDE_PATHS: ${{ inputs.include_paths }}

install.sh

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
CLI_VERSION="${CLI_VERSION:-latest}"
5+
ACTION_PATH="${GITHUB_ACTION_PATH:-$(pwd)}"
6+
BIN_PATH="${ACTION_PATH}/linear-release"
7+
8+
case "${RUNNER_OS:-}" in
9+
Linux)
10+
ARCH="$(uname -m)"
11+
if [[ "$ARCH" != "x86_64" && "$ARCH" != "amd64" ]]; then
12+
echo "::error::Unsupported Linux arch: $ARCH. Only x86_64 is supported."
13+
exit 1
14+
fi
15+
ASSET="linear-release-linux-x64"
16+
;;
17+
macOS)
18+
ARCH="$(uname -m)"
19+
if [[ "$ARCH" == "arm64" ]]; then
20+
ASSET="linear-release-darwin-arm64"
21+
elif [[ "$ARCH" == "x86_64" ]]; then
22+
ASSET="linear-release-darwin-x64"
23+
else
24+
echo "::error::Unsupported macOS arch: $ARCH. Only x86_64 and arm64 are supported."
25+
exit 1
26+
fi
27+
;;
28+
*)
29+
echo "::error::Unsupported OS: ${RUNNER_OS:-unknown}"
30+
exit 1
31+
;;
32+
esac
33+
34+
if [[ "$CLI_VERSION" == "latest" ]]; then
35+
URL="https://github.com/linear/linear-release/releases/latest/download/$ASSET"
36+
else
37+
URL="https://github.com/linear/linear-release/releases/download/$CLI_VERSION/$ASSET"
38+
fi
39+
40+
echo "Downloading Linear Release CLI from $URL"
41+
curl -fsSL "$URL" -o "$BIN_PATH"
42+
chmod +x "$BIN_PATH"
43+
44+
echo "Linear Release CLI installed at $BIN_PATH"

run.sh

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
ACTION_PATH="${GITHUB_ACTION_PATH:-$(pwd)}"
5+
BIN_PATH="${ACTION_PATH}/linear-release"
6+
7+
if [[ -z "${LINEAR_ACCESS_KEY:-}" ]]; then
8+
echo "::error::access_key input is required"
9+
exit 1
10+
fi
11+
12+
if [[ ! -x "$BIN_PATH" ]]; then
13+
echo "::error::Linear Release CLI not found at $BIN_PATH. Ensure the install step ran."
14+
exit 1
15+
fi
16+
17+
COMMAND="${COMMAND:-sync}"
18+
case "$COMMAND" in
19+
sync|complete|update)
20+
;;
21+
*)
22+
echo "::error::Invalid command '$COMMAND'. Must be: sync, complete, or update"
23+
exit 1
24+
;;
25+
esac
26+
27+
if [[ "$COMMAND" == "update" && -z "${INPUT_STAGE:-}" ]]; then
28+
echo "::error::stage input is required when command is 'update'"
29+
exit 1
30+
fi
31+
32+
args=()
33+
[[ -n "${INPUT_NAME:-}" ]] && args+=("--name=${INPUT_NAME}")
34+
[[ -n "${INPUT_VERSION:-}" ]] && args+=("--version=${INPUT_VERSION}")
35+
[[ -n "${INPUT_STAGE:-}" ]] && args+=("--stage=${INPUT_STAGE}")
36+
[[ -n "${INPUT_INCLUDE_PATHS:-}" ]] && args+=("--include-paths=${INPUT_INCLUDE_PATHS}")
37+
38+
echo "Running: $BIN_PATH $COMMAND ${args[*]:-}"
39+
"$BIN_PATH" "$COMMAND" ${args[@]+"${args[@]}"}

0 commit comments

Comments
 (0)