Skip to content

Commit c1429ab

Browse files
Merge pull request #71 from firecrawl/install-sh
add multi-channel distribution: binaries, install scripts, homebrew
2 parents 40b3fdd + b214bad commit c1429ab

11 files changed

Lines changed: 735 additions & 7 deletions

File tree

.github/workflows/publish.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ jobs:
2121

2222
steps:
2323
- name: Checkout repository
24-
uses: actions/checkout@v4
24+
uses: actions/checkout@v6
2525

2626
- name: Setup Node.js
27-
uses: actions/setup-node@v4
27+
uses: actions/setup-node@v6
2828
with:
2929
node-version: '24'
3030
registry-url: 'https://registry.npmjs.org'
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
name: Release Binaries
2+
3+
on:
4+
push:
5+
branches: [main, install-sh]
6+
paths:
7+
- 'package.json'
8+
- '.github/workflows/release-binaries.yml'
9+
- 'nfpm.yaml'
10+
workflow_dispatch:
11+
12+
permissions:
13+
contents: write
14+
15+
jobs:
16+
check-version:
17+
runs-on: ubuntu-latest
18+
name: Check for version bump
19+
outputs:
20+
version: ${{ steps.check.outputs.version }}
21+
released: ${{ steps.check.outputs.released }}
22+
dry_run: ${{ steps.check.outputs.dry_run }}
23+
steps:
24+
- name: Checkout repository
25+
uses: actions/checkout@v6
26+
with:
27+
fetch-depth: 0
28+
29+
- name: Check if version tag exists
30+
id: check
31+
run: |
32+
VERSION=$(node -p "require('./package.json').version")
33+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
34+
35+
# Dry run on non-main branches
36+
if [ "${{ github.ref_name }}" != "main" ]; then
37+
echo "dry_run=true" >> "$GITHUB_OUTPUT"
38+
echo "released=false" >> "$GITHUB_OUTPUT"
39+
echo "Dry run on branch ${{ github.ref_name }} — will build but not release"
40+
elif git rev-parse "v$VERSION" >/dev/null 2>&1; then
41+
echo "dry_run=false" >> "$GITHUB_OUTPUT"
42+
echo "released=true" >> "$GITHUB_OUTPUT"
43+
echo "v$VERSION already released — skipping"
44+
else
45+
echo "dry_run=false" >> "$GITHUB_OUTPUT"
46+
echo "released=false" >> "$GITHUB_OUTPUT"
47+
echo "New version detected: v$VERSION"
48+
fi
49+
50+
build:
51+
needs: check-version
52+
if: needs.check-version.outputs.released == 'false'
53+
strategy:
54+
matrix:
55+
include:
56+
- os: ubuntu-latest
57+
target: bun-linux-x64
58+
binary: firecrawl-linux-x64
59+
- os: ubuntu-latest
60+
target: bun-linux-arm64
61+
binary: firecrawl-linux-arm64
62+
- os: macos-latest
63+
target: bun-darwin-arm64
64+
binary: firecrawl-darwin-arm64
65+
- os: macos-latest
66+
target: bun-darwin-x64
67+
binary: firecrawl-darwin-x64
68+
- os: ubuntu-latest
69+
target: bun-windows-x64
70+
binary: firecrawl-windows-x64.exe
71+
72+
runs-on: ${{ matrix.os }}
73+
name: Build ${{ matrix.binary }}
74+
75+
steps:
76+
- name: Checkout repository
77+
uses: actions/checkout@v6
78+
79+
- name: Setup Bun
80+
uses: oven-sh/setup-bun@v2
81+
82+
- name: Install dependencies
83+
run: bun install --frozen-lockfile
84+
85+
- name: Build binary
86+
run: bun build src/index.ts --compile --target=${{ matrix.target }} --outfile ${{ matrix.binary }}
87+
88+
- name: Create tarball (Unix)
89+
if: "!contains(matrix.binary, 'windows')"
90+
run: tar -czf ${{ matrix.binary }}.tar.gz ${{ matrix.binary }}
91+
92+
- name: Create zip (Windows)
93+
if: contains(matrix.binary, 'windows')
94+
run: zip ${{ matrix.binary }}.zip ${{ matrix.binary }}
95+
96+
- name: Upload binary artifact
97+
uses: actions/upload-artifact@v7
98+
with:
99+
name: ${{ matrix.binary }}
100+
path: |
101+
${{ matrix.binary }}
102+
${{ matrix.binary }}.tar.gz
103+
${{ matrix.binary }}.zip
104+
if-no-files-found: ignore
105+
106+
release:
107+
needs: [check-version, build]
108+
runs-on: ubuntu-latest
109+
name: Create release and upload assets
110+
111+
steps:
112+
- name: Checkout repository
113+
uses: actions/checkout@v6
114+
with:
115+
fetch-depth: 0
116+
117+
- name: Download all artifacts
118+
uses: actions/download-artifact@v8
119+
with:
120+
path: artifacts
121+
122+
- name: Collect release files
123+
run: |
124+
mkdir -p release binaries
125+
find artifacts -type f \( -name "*.tar.gz" -o -name "*.zip" \) -exec cp {} release/ \;
126+
# Copy raw binaries for nfpm packaging
127+
for dir in artifacts/firecrawl-linux-*/; do
128+
find "$dir" -type f ! -name "*.tar.gz" ! -name "*.zip" -exec cp {} binaries/ \;
129+
done
130+
chmod +x binaries/*
131+
ls -la release/
132+
ls -la binaries/
133+
134+
- name: Install nfpm
135+
run: |
136+
NFPM_VERSION=$(gh release view --repo goreleaser/nfpm --json tagName --jq '.tagName' | sed 's/^v//')
137+
curl -sfL "https://github.com/goreleaser/nfpm/releases/download/v${NFPM_VERSION}/nfpm_${NFPM_VERSION}_Linux_x86_64.tar.gz" | tar -xz -C /usr/local/bin nfpm
138+
nfpm --version
139+
env:
140+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
141+
142+
- name: Build Linux packages
143+
run: |
144+
VERSION="${{ needs.check-version.outputs.version }}"
145+
146+
# linux amd64
147+
export BINARY=binaries/firecrawl-linux-x64 VERSION="$VERSION" ARCH=amd64
148+
envsubst < nfpm.yaml > /tmp/nfpm-amd64.yaml
149+
for fmt in deb rpm apk archlinux; do
150+
nfpm package --config /tmp/nfpm-amd64.yaml --packager "$fmt" --target release/
151+
done
152+
153+
# linux arm64
154+
export BINARY=binaries/firecrawl-linux-arm64 ARCH=arm64
155+
envsubst < nfpm.yaml > /tmp/nfpm-arm64.yaml
156+
for fmt in deb rpm apk archlinux; do
157+
nfpm package --config /tmp/nfpm-arm64.yaml --packager "$fmt" --target release/
158+
done
159+
160+
ls -la release/
161+
162+
- name: Generate checksums
163+
run: |
164+
cd release
165+
sha256sum * > checksums.txt
166+
cat checksums.txt
167+
168+
- name: Summary (dry run)
169+
if: needs.check-version.outputs.dry_run == 'true'
170+
run: |
171+
echo "## Dry Run — Release v${{ needs.check-version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
172+
echo "" >> $GITHUB_STEP_SUMMARY
173+
echo "All artifacts built and packaged successfully:" >> $GITHUB_STEP_SUMMARY
174+
echo '```' >> $GITHUB_STEP_SUMMARY
175+
ls -lh release/ >> $GITHUB_STEP_SUMMARY
176+
echo '```' >> $GITHUB_STEP_SUMMARY
177+
echo "" >> $GITHUB_STEP_SUMMARY
178+
echo "**No release created — this is a dry run on branch \`${{ github.ref_name }}\`.**" >> $GITHUB_STEP_SUMMARY
179+
180+
- name: Generate release notes
181+
if: needs.check-version.outputs.dry_run != 'true'
182+
run: |
183+
PREV_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
184+
if [ -n "$PREV_TAG" ]; then
185+
git log --pretty=format:"- %s" "$PREV_TAG..HEAD" -- | head -50 > /tmp/release-notes.md
186+
else
187+
echo "Initial release" > /tmp/release-notes.md
188+
fi
189+
190+
- name: Create tag and GitHub release
191+
if: needs.check-version.outputs.dry_run != 'true'
192+
env:
193+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
194+
run: |
195+
VERSION="v${{ needs.check-version.outputs.version }}"
196+
git tag "$VERSION"
197+
git push origin "$VERSION"
198+
gh release create "$VERSION" release/* \
199+
--repo "${{ github.repository }}" \
200+
--title "Firecrawl CLI $VERSION" \
201+
--notes-file /tmp/release-notes.md

.github/workflows/sync-plugin.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
runs-on: ubuntu-latest
1414
steps:
1515
- name: Checkout CLI repo
16-
uses: actions/checkout@v4
16+
uses: actions/checkout@v6
1717
with:
1818
path: cli
1919

.github/workflows/sync-skills.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
runs-on: ubuntu-latest
1313
steps:
1414
- name: Checkout CLI repo
15-
uses: actions/checkout@v4
15+
uses: actions/checkout@v6
1616
with:
1717
path: cli
1818

.github/workflows/test.yml

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ jobs:
1313

1414
steps:
1515
- name: Checkout repository
16-
uses: actions/checkout@v4
16+
uses: actions/checkout@v6
1717

1818
- name: Setup Node.js
19-
uses: actions/setup-node@v4
19+
uses: actions/setup-node@v6
2020
with:
2121
node-version: '18'
2222

@@ -39,3 +39,48 @@ jobs:
3939

4040
- name: Run tests
4141
run: pnpm run test
42+
43+
test-binary:
44+
if: github.event_name == 'pull_request'
45+
strategy:
46+
fail-fast: false
47+
matrix:
48+
include:
49+
- os: ubuntu-latest
50+
target: bun-linux-x64
51+
binary: firecrawl-linux-x64
52+
- os: macos-latest
53+
target: bun-darwin-arm64
54+
binary: firecrawl-darwin-arm64
55+
- os: windows-latest
56+
target: bun-windows-x64
57+
binary: firecrawl-windows-x64.exe
58+
59+
runs-on: ${{ matrix.os }}
60+
name: Binary test (${{ matrix.os }})
61+
62+
steps:
63+
- name: Checkout repository
64+
uses: actions/checkout@v6
65+
66+
- name: Setup Bun
67+
uses: oven-sh/setup-bun@v2
68+
69+
- name: Install dependencies
70+
run: bun install --frozen-lockfile
71+
72+
- name: Compile binary
73+
run: bun build src/index.ts --compile --target=${{ matrix.target }} --outfile ${{ matrix.binary }}
74+
75+
- name: Verify binary runs (Unix)
76+
if: runner.os != 'Windows'
77+
run: |
78+
chmod +x ${{ matrix.binary }}
79+
./${{ matrix.binary }} --version
80+
./${{ matrix.binary }} --help
81+
82+
- name: Verify binary runs (Windows)
83+
if: runner.os == 'Windows'
84+
run: |
85+
.\${{ matrix.binary }} --version
86+
.\${{ matrix.binary }} --help

homebrew/firecrawl-cli.rb

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
class FirecrawlCli < Formula
2+
desc "CLI for Firecrawl - web scraping, search, and browser automation"
3+
homepage "https://firecrawl.dev"
4+
version "1.10.0"
5+
license "ISC"
6+
7+
on_macos do
8+
on_arm do
9+
url "https://github.com/firecrawl/cli/releases/download/v#{version}/firecrawl-darwin-arm64.tar.gz"
10+
sha256 "PLACEHOLDER"
11+
end
12+
on_intel do
13+
url "https://github.com/firecrawl/cli/releases/download/v#{version}/firecrawl-darwin-x64.tar.gz"
14+
sha256 "PLACEHOLDER"
15+
end
16+
end
17+
on_linux do
18+
on_arm do
19+
url "https://github.com/firecrawl/cli/releases/download/v#{version}/firecrawl-linux-arm64.tar.gz"
20+
sha256 "PLACEHOLDER"
21+
end
22+
on_intel do
23+
url "https://github.com/firecrawl/cli/releases/download/v#{version}/firecrawl-linux-x64.tar.gz"
24+
sha256 "PLACEHOLDER"
25+
end
26+
end
27+
28+
def install
29+
if OS.mac?
30+
if Hardware::CPU.arm?
31+
bin.install "firecrawl-darwin-arm64" => "firecrawl"
32+
else
33+
bin.install "firecrawl-darwin-x64" => "firecrawl"
34+
end
35+
elsif OS.linux?
36+
if Hardware::CPU.arm?
37+
bin.install "firecrawl-linux-arm64" => "firecrawl"
38+
else
39+
bin.install "firecrawl-linux-x64" => "firecrawl"
40+
end
41+
end
42+
end
43+
44+
test do
45+
assert_match version.to_s, shell_output("#{bin}/firecrawl --version")
46+
end
47+
end

nfpm.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
name: firecrawl
2+
description: CLI for Firecrawl - web scraping, search, and browser automation
3+
homepage: https://firecrawl.dev
4+
maintainer: Firecrawl <support@firecrawl.dev>
5+
license: ISC
6+
vendor: Firecrawl
7+
version: ${VERSION}
8+
arch: ${ARCH}
9+
10+
contents:
11+
- src: ${BINARY}
12+
dst: /usr/bin/firecrawl
13+
file_info:
14+
mode: 0755

package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@
2020
"test:watch": "vitest",
2121
"test": "vitest run",
2222
"publish-beta": "npm publish --tag beta",
23-
"publish-prod": "npm publish --access public"
23+
"publish-prod": "npm publish --access public",
24+
"build:binary": "bash scripts/build-binaries.sh",
25+
"build:binary:darwin": "bash scripts/build-binaries.sh darwin",
26+
"build:binary:linux": "bash scripts/build-binaries.sh linux",
27+
"build:binary:windows": "bash scripts/build-binaries.sh windows"
2428
},
2529
"lint-staged": {
2630
"*.{ts,json,md}": [

0 commit comments

Comments
 (0)