Skip to content

Commit e16a577

Browse files
committed
v0.1.0 — initial public release
0 parents  commit e16a577

33 files changed

Lines changed: 2157 additions & 0 deletions

.github/workflows/ci.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
build:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v4
14+
15+
- uses: actions/setup-go@v5
16+
with:
17+
go-version: "1.26"
18+
19+
- run: go build -o cb ./cmd/cb
20+
21+
- run: go vet ./...

.github/workflows/release.yml

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags: ["v*"]
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
release:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@v4
16+
17+
- uses: actions/setup-go@v5
18+
with:
19+
go-version: "1.26"
20+
21+
- name: Get version
22+
id: version
23+
run: |
24+
if [ "${{ github.ref_type }}" = "tag" ]; then
25+
TAG="${{ github.ref_name }}"
26+
else
27+
TAG="dev-build"
28+
fi
29+
VERSION=$(printf '%s' "$TAG" | sed 's/^v//')
30+
echo "tag=$TAG" >> $GITHUB_OUTPUT
31+
echo "version=$VERSION" >> $GITHUB_OUTPUT
32+
33+
- name: Build assets
34+
env:
35+
VERSION: ${{ steps.version.outputs.version }}
36+
run: |
37+
mkdir -p dist
38+
39+
for target in linux/amd64 linux/arm64; do
40+
GOOS="${target%/*}"
41+
GOARCH="${target#*/}"
42+
TARGET="${GOOS}_${GOARCH}"
43+
BIN_DIR="dist/${TARGET}"
44+
ASSET="cb_${VERSION}_${TARGET}.tar.gz"
45+
46+
mkdir -p "$BIN_DIR"
47+
CGO_ENABLED=0 GOOS="$GOOS" GOARCH="$GOARCH" \
48+
go build -trimpath -ldflags "-s -w -X main.version=${VERSION}" \
49+
-o "${BIN_DIR}/cb" ./cmd/cb
50+
tar -czf "$ASSET" -C "$BIN_DIR" cb
51+
52+
echo "Built $ASSET ($(wc -c < "$ASSET") bytes)"
53+
done
54+
55+
- name: Create release and upload assets
56+
env:
57+
GH_TOKEN: ${{ github.token }}
58+
TAG: ${{ steps.version.outputs.tag }}
59+
VERSION: ${{ steps.version.outputs.version }}
60+
run: |
61+
gh release create "$TAG" \
62+
--title "$TAG" \
63+
--notes "Release $TAG" \
64+
--target "$GITHUB_SHA" \
65+
./cb_*.tar.gz

.gitignore

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Binary
2+
/cb
3+
/cmd/cb/cb
4+
5+
# Build
6+
/dist/
7+
8+
# IDE
9+
.idea/
10+
.vscode/
11+
*.swp
12+
*.swo
13+
14+
# OS
15+
.DS_Store
16+
Thumbs.db
17+
18+
# Test coverage
19+
*.out
20+
coverage.html
21+
22+
# Dependencies (if vendored)
23+
/vendor/

README.md

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
# cb (Codeberg CLI)
2+
3+
`cb` is a minimal, `gh`-style CLI for Codeberg focused on practical daily workflows.
4+
5+
Current scope:
6+
- auth login/logout/status
7+
- repo list/create/migrate
8+
- self update
9+
10+
## Install / Update / Uninstall
11+
12+
Install:
13+
14+
```bash
15+
curl -fsSL https://raw.githubusercontent.com/rishabyd/codeberg-cli/main/install.sh | sh
16+
```
17+
18+
Update:
19+
20+
```bash
21+
cb update
22+
```
23+
24+
Uninstall:
25+
26+
```bash
27+
curl -fsSL https://raw.githubusercontent.com/rishabyd/codeberg-cli/main/uninstall.sh | sh
28+
```
29+
30+
From local checkout:
31+
32+
```bash
33+
./install.sh
34+
./uninstall.sh
35+
```
36+
37+
## Command Syntax
38+
39+
```bash
40+
cb auth <action>
41+
cb repo <action> [target]
42+
cb update
43+
```
44+
45+
Auth:
46+
47+
```bash
48+
cb auth login
49+
cb auth status
50+
cb auth logout
51+
```
52+
53+
Repo:
54+
55+
```bash
56+
cb repo list [--limit <n>]
57+
cb repo create <name> [flags]
58+
cb repo migrate <owner/repo> [--clone]
59+
```
60+
61+
Create flags:
62+
- `-d, --description <text>`
63+
- `--public`
64+
- `--private`
65+
- `--add-readme`
66+
- `-c, --clone`
67+
68+
## Common Workflows
69+
70+
Create repository:
71+
72+
```bash
73+
cb repo create my-project --public
74+
cb repo create my-project --private --description "internal tools"
75+
cb repo create my-project --public --add-readme --clone
76+
```
77+
78+
Migrate repository:
79+
80+
```bash
81+
cb repo migrate owner/repo
82+
cb repo migrate owner/repo --clone
83+
```
84+
85+
`cb repo migrate` performs public GitHub -> public Codeberg migration and includes:
86+
- source code
87+
- issues
88+
- pull requests
89+
- wiki
90+
- labels
91+
- milestones
92+
- releases
93+
94+
## Troubleshooting
95+
96+
- DNS failure (`lookup codeberg.org ... server misbehaving`) is a local network resolver issue, not token expiry.
97+
- If refresh token is revoked or expired, run `cb auth login` again.
98+
- Verify auth and API reachability with `cb auth status`.
99+
- Ensure git HTTPS helper is configured: `git config --global --get credential.https://codeberg.org.helper`.
100+
101+
## Exit Codes
102+
103+
- `0`: success
104+
- `1`: runtime/auth/network/api error
105+
- `2`: usage or argument error
106+
107+
## Build from Source
108+
109+
```bash
110+
go build -o cb ./cmd/cb
111+
./cb --help
112+
```
113+
114+
## Platform Compatibility
115+
116+
Official prebuilt release binaries are provided for:
117+
- Linux x86_64 (`linux_amd64`)
118+
- Linux ARM64 (`linux_arm64`)
119+
120+
Other platforms can use source build (`go build -o cb ./cmd/cb`).
121+
122+
## Versioning
123+
124+
This project uses Go-native tag-based versioning.
125+
126+
- Local/dev builds show version `dev`.
127+
- Release builds inject version from git tag using Go linker flags.
128+
129+
Create and publish a release:
130+
131+
```bash
132+
git status
133+
git tag -a v0.4.13 -m "v0.4.13"
134+
git push origin main --tags
135+
```
136+
137+
To verify locally:
138+
139+
```bash
140+
go build -ldflags "-X main.version=0.4.13" -o cb ./cmd/cb
141+
./cb --version
142+
```
143+
144+
Required secret for releases:
145+
- `GITHUB_TOKEN` (provided automatically by GitHub Actions)

cmd/cb/main.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
"github.com/rishabyd/codeberg-cli/internal/commands"
8+
)
9+
10+
var version = "0.1.0"
11+
12+
func main() {
13+
exitCode, err := run()
14+
if err != nil {
15+
fmt.Fprintln(os.Stderr, err)
16+
os.Exit(exitCode)
17+
}
18+
}
19+
20+
func run() (int, error) {
21+
err := commands.Execute(version, os.Args[1:])
22+
if err != nil {
23+
if commands.IsUsageError(err) {
24+
return 2, err
25+
}
26+
return 1, err
27+
}
28+
return 0, nil
29+
}

go.mod

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
module github.com/rishabyd/codeberg-cli
2+
3+
go 1.26
4+
5+
require github.com/spf13/cobra v1.10.2
6+
7+
require (
8+
github.com/inconshreveable/mousetrap v1.1.0 // indirect
9+
github.com/spf13/pflag v1.0.9 // indirect
10+
)

go.sum

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
2+
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
3+
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
4+
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
5+
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
6+
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
7+
github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
8+
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
9+
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
10+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

install.sh

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#!/bin/sh
2+
set -eu
3+
4+
REPO="rishabyd/codeberg-cli"
5+
INSTALL_DIR="/usr/local/bin"
6+
BINARY_NAME="cb"
7+
8+
detect_os() {
9+
case "$(uname -s)" in
10+
Linux*) echo "linux" ;;
11+
*) echo "Unsupported operating system" >&2; exit 1 ;;
12+
esac
13+
}
14+
15+
detect_arch() {
16+
case "$(uname -m)" in
17+
x86_64|amd64) echo "amd64" ;;
18+
aarch64|arm64) echo "arm64" ;;
19+
*) echo "Unsupported architecture" >&2; exit 1 ;;
20+
esac
21+
}
22+
23+
require_cmd() {
24+
command -v "$1" >/dev/null 2>&1 || { echo "Missing required command: $1" >&2; exit 1; }
25+
}
26+
27+
fetch_latest_tag() {
28+
url="https://api.github.com/repos/${REPO}/releases/latest"
29+
if command -v curl >/dev/null 2>&1; then
30+
curl -fsSL "$url" | sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -n1
31+
return
32+
fi
33+
if command -v wget >/dev/null 2>&1; then
34+
wget -qO- "$url" | sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -n1
35+
return
36+
fi
37+
echo "Need curl or wget" >&2
38+
exit 1
39+
}
40+
41+
main() {
42+
require_cmd tar
43+
os=$(detect_os)
44+
arch=$(detect_arch)
45+
tag=$(fetch_latest_tag)
46+
[ -n "$tag" ] || { echo "Could not resolve latest release" >&2; exit 1; }
47+
48+
version=$(printf "%s" "$tag" | sed 's/^v//')
49+
asset="${BINARY_NAME}_${version}_${os}_${arch}.tar.gz"
50+
url="https://github.com/${REPO}/releases/download/${tag}/${asset}"
51+
52+
tmp_dir=$(mktemp -d)
53+
trap 'rm -rf "$tmp_dir"' EXIT
54+
archive_path="${tmp_dir}/${asset}"
55+
56+
echo "Downloading ${asset}..."
57+
if command -v curl >/dev/null 2>&1; then
58+
curl -fsSL "$url" -o "$archive_path"
59+
else
60+
wget -qO "$archive_path" "$url"
61+
fi
62+
63+
tar -xzf "$archive_path" -C "$tmp_dir"
64+
chmod +x "${tmp_dir}/${BINARY_NAME}"
65+
66+
target="${INSTALL_DIR}/${BINARY_NAME}"
67+
if [ -w "$INSTALL_DIR" ]; then
68+
mv "${tmp_dir}/${BINARY_NAME}" "$target"
69+
else
70+
echo "Installing to ${target} (sudo may prompt)..."
71+
sudo mv "${tmp_dir}/${BINARY_NAME}" "$target"
72+
fi
73+
74+
echo "Installed ${BINARY_NAME} ${tag} to ${target}"
75+
76+
echo "Run: cb auth login"
77+
}
78+
79+
main

0 commit comments

Comments
 (0)