Skip to content

Commit e50ac8a

Browse files
committed
initial release: sf — terminal file manager written in ARO
Midnight Commander-style dual-panel file manager with keyboard navigation, file preview, and directory browsing. Includes CI/CD pipeline with signed macOS builds and Homebrew tap support.
0 parents  commit e50ac8a

File tree

9 files changed

+870
-0
lines changed

9 files changed

+870
-0
lines changed

.github/workflows/build.yml

Lines changed: 341 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,341 @@
1+
name: Build & Release
2+
3+
on:
4+
push:
5+
branches: [main]
6+
tags: ['*']
7+
pull_request:
8+
branches: [main]
9+
10+
env:
11+
ARO_VERSION: latest
12+
SWIFT_VERSION: '6.2.1'
13+
14+
jobs:
15+
# ===========================================================================
16+
# Check — syntax-check on both platforms
17+
# ===========================================================================
18+
check:
19+
strategy:
20+
fail-fast: false
21+
matrix:
22+
include:
23+
- os: ubuntu-22.04
24+
asset: aro-linux-amd64.tar.gz
25+
- os: macos-latest
26+
asset: aro-macos-arm64.tar.gz
27+
runs-on: ${{ matrix.os }}
28+
steps:
29+
- name: Checkout repository
30+
uses: actions/checkout@v4
31+
32+
- name: Install dependencies (Linux)
33+
if: runner.os == 'Linux'
34+
run: |
35+
sudo apt-get update -qq
36+
sudo apt-get install -y -qq libgit2-dev
37+
wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo gpg --dearmor -o /usr/share/keyrings/llvm-archive-keyring.gpg
38+
echo "deb [signed-by=/usr/share/keyrings/llvm-archive-keyring.gpg] http://apt.llvm.org/jammy/ llvm-toolchain-jammy-20 main" | sudo tee /etc/apt/sources.list.d/llvm.list
39+
sudo apt-get update -qq
40+
sudo apt-get install -y -qq libllvm20
41+
42+
- name: Install ARO (Linux)
43+
if: runner.os == 'Linux'
44+
run: |
45+
if [ "$ARO_VERSION" = "latest" ]; then
46+
DOWNLOAD_URL=$(curl -s https://api.github.com/repos/arolang/aro/releases/latest \
47+
| grep "browser_download_url.*${{ matrix.asset }}" \
48+
| cut -d '"' -f 4)
49+
else
50+
DOWNLOAD_URL="https://github.com/arolang/aro/releases/download/${ARO_VERSION}/${{ matrix.asset }}"
51+
fi
52+
curl -fsSL "$DOWNLOAD_URL" | tar xz
53+
sudo mv aro /usr/local/bin/
54+
sudo mv libARORuntime.a /usr/local/lib/
55+
aro --version
56+
57+
- name: Install ARO (macOS)
58+
if: runner.os == 'macOS'
59+
run: |
60+
brew tap arolang/aro
61+
brew install aro libgit2 llvm@20
62+
aro --version
63+
64+
- name: Check code
65+
run: aro check .
66+
67+
# ===========================================================================
68+
# Build — compile for macOS (signed) and Linux
69+
# ===========================================================================
70+
build-linux:
71+
needs: check
72+
runs-on: ubuntu-22.04
73+
steps:
74+
- name: Checkout repository
75+
uses: actions/checkout@v4
76+
77+
- name: Install Swift
78+
run: |
79+
curl -fsSL "https://download.swift.org/swift-${SWIFT_VERSION}-release/ubuntu2204/swift-${SWIFT_VERSION}-RELEASE/swift-${SWIFT_VERSION}-RELEASE-ubuntu22.04.tar.gz" -o swift.tar.gz
80+
sudo mkdir -p /usr/share/swift
81+
sudo tar xzf swift.tar.gz -C /usr/share/swift --strip-components=1
82+
echo "/usr/share/swift/usr/bin" >> $GITHUB_PATH
83+
rm swift.tar.gz
84+
85+
- name: Install dependencies
86+
run: |
87+
sudo apt-get update -qq
88+
sudo apt-get install -y -qq libgit2-dev
89+
wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo gpg --dearmor -o /usr/share/keyrings/llvm-archive-keyring.gpg
90+
echo "deb [signed-by=/usr/share/keyrings/llvm-archive-keyring.gpg] http://apt.llvm.org/jammy/ llvm-toolchain-jammy-20 main" | sudo tee /etc/apt/sources.list.d/llvm.list
91+
sudo apt-get update -qq
92+
sudo apt-get install -y -qq llvm-20
93+
echo "/usr/lib/llvm-20/bin" >> $GITHUB_PATH
94+
95+
- name: Install ARO
96+
run: |
97+
if [ "$ARO_VERSION" = "latest" ]; then
98+
DOWNLOAD_URL=$(curl -s https://api.github.com/repos/arolang/aro/releases/latest \
99+
| grep "browser_download_url.*aro-linux-amd64.tar.gz" \
100+
| cut -d '"' -f 4)
101+
else
102+
DOWNLOAD_URL="https://github.com/arolang/aro/releases/download/${ARO_VERSION}/aro-linux-amd64.tar.gz"
103+
fi
104+
curl -fsSL "$DOWNLOAD_URL" | tar xz
105+
sudo mv aro /usr/local/bin/
106+
sudo mv libARORuntime.a /usr/local/lib/
107+
108+
- name: Build
109+
run: aro build . --optimize --strip --size -o sf
110+
111+
- name: Upload artifact
112+
uses: actions/upload-artifact@v4
113+
with:
114+
name: sf-linux-amd64
115+
path: sf
116+
117+
build-macos:
118+
needs: check
119+
runs-on: macos-latest
120+
steps:
121+
- name: Checkout repository
122+
uses: actions/checkout@v4
123+
124+
- name: Install Swift via swiftly
125+
run: |
126+
curl -fsSL https://swiftlang.github.io/swiftly/swiftly-install.sh | bash -s -- --no-modify-profile -y
127+
. ~/.swiftly/env.sh
128+
swiftly install $SWIFT_VERSION
129+
echo "$HOME/.swiftly/bin" >> $GITHUB_PATH
130+
131+
- name: Install ARO
132+
run: |
133+
brew tap arolang/aro
134+
brew install aro libgit2 llvm@20
135+
echo "/opt/homebrew/opt/llvm@20/bin" >> $GITHUB_PATH
136+
137+
- name: Import Code Signing Certificate
138+
if: github.ref_type == 'tag'
139+
env:
140+
APPLE_CERTIFICATE_BASE64: ${{ secrets.APPLE_CERTIFICATE_BASE64 }}
141+
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
142+
run: |
143+
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
144+
KEYCHAIN_PASSWORD=$(openssl rand -base64 32)
145+
146+
echo "$APPLE_CERTIFICATE_BASE64" | base64 --decode > certificate.p12
147+
148+
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
149+
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
150+
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
151+
152+
security import certificate.p12 \
153+
-P "$APPLE_CERTIFICATE_PASSWORD" \
154+
-A \
155+
-t cert \
156+
-f pkcs12 \
157+
-k $KEYCHAIN_PATH
158+
159+
security list-keychain -d user -s $KEYCHAIN_PATH
160+
security set-key-partition-list \
161+
-S apple-tool:,apple: \
162+
-s \
163+
-k "$KEYCHAIN_PASSWORD" \
164+
$KEYCHAIN_PATH
165+
166+
rm certificate.p12
167+
168+
- name: Build (signed)
169+
if: github.ref_type == 'tag'
170+
env:
171+
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
172+
run: |
173+
aro build . --sign "$APPLE_TEAM_ID" --optimize --strip --size -o sf
174+
codesign --verify --verbose sf
175+
176+
- name: Build (unsigned)
177+
if: github.ref_type != 'tag'
178+
run: aro build . --optimize --strip --size -o sf
179+
180+
- name: Notarize Binary
181+
if: github.ref_type == 'tag'
182+
env:
183+
APPLE_ID: ${{ secrets.APPLE_ID }}
184+
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
185+
APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }}
186+
run: |
187+
zip -r sf.zip sf
188+
xcrun notarytool submit sf.zip \
189+
--apple-id "$APPLE_ID" \
190+
--team-id "$APPLE_TEAM_ID" \
191+
--password "$APPLE_APP_PASSWORD" \
192+
--wait
193+
# Staple may fail for CLI tools — that's OK
194+
xcrun stapler staple sf || true
195+
196+
- name: Upload artifact
197+
uses: actions/upload-artifact@v4
198+
with:
199+
name: sf-macos-arm64
200+
path: sf
201+
202+
# ===========================================================================
203+
# Release — create GitHub release on tag push
204+
# ===========================================================================
205+
release:
206+
name: Create Release
207+
needs: [build-linux, build-macos]
208+
runs-on: ubuntu-latest
209+
if: github.ref_type == 'tag'
210+
permissions:
211+
contents: write
212+
steps:
213+
- name: Checkout repository
214+
uses: actions/checkout@v4
215+
216+
- name: Download all artifacts
217+
uses: actions/download-artifact@v4
218+
with:
219+
path: artifacts
220+
221+
- name: Package release assets
222+
run: |
223+
cd artifacts/sf-linux-amd64
224+
chmod +x sf
225+
tar -czvf ../sf-linux-amd64.tar.gz sf
226+
cd ../..
227+
228+
cd artifacts/sf-macos-arm64
229+
chmod +x sf
230+
tar -czvf ../sf-macos-arm64.tar.gz sf
231+
cd ../..
232+
233+
- name: Extract version from tag
234+
id: version
235+
run: |
236+
VERSION="${{ github.ref_name }}"
237+
VERSION="${VERSION#v}"
238+
echo "version=${VERSION}" >> $GITHUB_OUTPUT
239+
240+
- name: Create GitHub Release
241+
uses: softprops/action-gh-release@v2
242+
with:
243+
name: sf ${{ steps.version.outputs.version }}
244+
draft: false
245+
prerelease: ${{ contains(github.ref_name, '-') }}
246+
generate_release_notes: true
247+
files: |
248+
artifacts/sf-linux-amd64.tar.gz
249+
artifacts/sf-macos-arm64.tar.gz
250+
body: |
251+
## ShowFiles ${{ steps.version.outputs.version }}
252+
253+
A Midnight Commander-style terminal file manager written in ARO.
254+
255+
### Downloads
256+
257+
| Platform | Architecture | Download |
258+
|----------|--------------|----------|
259+
| macOS | Apple Silicon | [sf-macos-arm64.tar.gz](https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/sf-macos-arm64.tar.gz) |
260+
| Linux | x86_64 | [sf-linux-amd64.tar.gz](https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/sf-linux-amd64.tar.gz) |
261+
262+
### Installation
263+
264+
**macOS (Homebrew)**
265+
```bash
266+
brew tap arolang/applications
267+
brew install sf
268+
```
269+
270+
**macOS (Manual)**
271+
```bash
272+
curl -fsSL https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/sf-macos-arm64.tar.gz | tar xz
273+
sudo mv sf /usr/local/bin/
274+
```
275+
276+
**Linux**
277+
```bash
278+
curl -fsSL https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/sf-linux-amd64.tar.gz | tar xz
279+
sudo mv sf /usr/local/bin/
280+
```
281+
282+
# ======================================================================
283+
# Update Homebrew Formula
284+
# ======================================================================
285+
- name: Update Homebrew Formula
286+
continue-on-error: true
287+
env:
288+
HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
289+
run: |
290+
SHA256_MACOS=$(shasum -a 256 artifacts/sf-macos-arm64.tar.gz | awk '{print $1}')
291+
SHA256_LINUX=$(shasum -a 256 artifacts/sf-linux-amd64.tar.gz | awk '{print $1}')
292+
VERSION="${{ steps.version.outputs.version }}"
293+
REPO="${{ github.repository }}"
294+
TAG="${{ github.ref_name }}"
295+
296+
echo "Version: $VERSION"
297+
echo "SHA256 macOS: $SHA256_MACOS"
298+
echo "SHA256 Linux: $SHA256_LINUX"
299+
300+
git clone https://x-access-token:${HOMEBREW_TAP_TOKEN}@github.com/arolang/homebrew-applications.git
301+
cd homebrew-applications
302+
mkdir -p Formula
303+
304+
{
305+
echo 'class Sf < Formula'
306+
echo ' desc "Midnight Commander-style terminal file manager written in ARO"'
307+
echo " homepage \"https://github.com/${REPO}\""
308+
echo " version \"${VERSION}\""
309+
echo ' license "MIT"'
310+
echo ''
311+
echo ' on_macos do'
312+
echo ' depends_on arch: :arm64'
313+
echo " url \"https://github.com/${REPO}/releases/download/${TAG}/sf-macos-arm64.tar.gz\""
314+
echo " sha256 \"${SHA256_MACOS}\""
315+
echo ' end'
316+
echo ''
317+
echo ' on_linux do'
318+
echo " url \"https://github.com/${REPO}/releases/download/${TAG}/sf-linux-amd64.tar.gz\""
319+
echo " sha256 \"${SHA256_LINUX}\""
320+
echo ' end'
321+
echo ''
322+
echo ' def install'
323+
echo ' bin.install "sf"'
324+
echo ' end'
325+
echo ''
326+
echo ' test do'
327+
echo ' assert_match version.to_s, shell_output("#{bin}/sf --version")'
328+
echo ' end'
329+
echo 'end'
330+
} > Formula/sf.rb
331+
332+
git config user.name "github-actions[bot]"
333+
git config user.email "github-actions[bot]@users.noreply.github.com"
334+
335+
git add Formula/sf.rb
336+
if git diff --staged --quiet; then
337+
echo "No changes to formula"
338+
else
339+
git commit -m "chore: update sf to version ${VERSION}"
340+
git push https://x-access-token:${HOMEBREW_TAP_TOKEN}@github.com/arolang/homebrew-applications.git main
341+
fi

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/sf
2+
/.idea
3+
/.DS_Store

0 commit comments

Comments
 (0)