fix(packages): use runtime dir for GitHub binaries

This commit is contained in:
Duy Nguyen committed 2026-05-18 21:43:03 +07:00
1 parent 077e81c990
commit c174279e01
8 files changed
+41 -13

No files matched your search

+1 -1
View File
@@ -18,7 +18,7 @@ import (
// GOCLAW_PACKAGES_GITHUB_TOKEN optional PAT (boosts rate limit, enables private repos)
// GOCLAW_PACKAGES_MAX_ASSET_SIZE_MB default 200
// GOCLAW_PACKAGES_GITHUB_ALLOWED_ORGS comma-separated allowlist (empty = all allowed)
// GOCLAW_PACKAGES_GITHUB_BIN_DIR default /app/data/.runtime/bin
// GOCLAW_PACKAGES_GITHUB_BIN_DIR default {runtimeDir}/bin
// GOCLAW_PACKAGES_GITHUB_MANIFEST default {BIN_DIR}/../github-packages.json
func initGitHubInstaller() {
cfg := &skills.GitHubPackagesConfig{
+1 -1
View File
@@ -217,7 +217,7 @@ github:owner/repo[@tag]
```
Admin-only, SHA256-verified, ELF-validated, with a release-picker UI. Binaries
land in `/app/data/.runtime/bin/` (on `$PATH`). See
land in `{runtimeDir}/bin/` (on `$PATH`). See
[`docs/packages-github.md`](./packages-github.md) for syntax, configuration,
security posture, and troubleshooting (especially musl/glibc compatibility).
+3 -3
View File
@@ -24,7 +24,7 @@ Examples:
4. Verifies SHA256 if the publisher ships `checksums.txt` / `SHA256SUMS`
5. Validates ELF magic bytes + 64-bit class + machine matches runtime arch
6. Extracts archive safely (tar.gz / zip / raw binary) with path-traversal + zip-bomb guards
7. Installs to `/app/data/.runtime/bin/` (prepended to `$PATH`)
7. Installs to `{runtimeDir}/bin/` (prepended to `$PATH`)
8. Persists a manifest for later listing + uninstall
## Usage
@@ -69,7 +69,7 @@ token in `config.json`.
| `GOCLAW_PACKAGES_GITHUB_TOKEN` | `""` | Optional PAT: rate 60/hr → 5000/hr + private repo access |
| `GOCLAW_PACKAGES_MAX_ASSET_SIZE_MB` | `200` | Applies to both download cap and 2× uncompressed cap |
| `GOCLAW_PACKAGES_GITHUB_ALLOWED_ORGS` | `""` | Comma-separated allowlist (empty = all orgs allowed) |
| `GOCLAW_PACKAGES_GITHUB_BIN_DIR` | `/app/data/.runtime/bin` | Where extracted binaries land |
| `GOCLAW_PACKAGES_GITHUB_BIN_DIR` | `{runtimeDir}/bin` | Where extracted binaries land |
| `GOCLAW_PACKAGES_GITHUB_MANIFEST` | `{bin_dir}/../github-packages.json` | Manifest path |
Token scopes:
@@ -133,7 +133,7 @@ the release. Do not force-install; report upstream.
## Limitations (Phase 1)
- Linux-only (Lite/Desktop editions not yet supported)
- Docker edition only (runtime dir `/app/data/.runtime/bin`)
- Docker and bare-metal gateway editions (default runtime dir resolves to `/app/data/.runtime/bin` in Docker or `/var/lib/goclaw/data/.runtime/bin` on bare-metal Linux)
- Installs all top-level executables in an archive (no interactive picker if
archive contains multiple binaries)
- No version history / rollback — re-installing replaces in place
+13
View File
@@ -6,6 +6,19 @@ Significant changes, features, and fixes in reverse chronological order.
## 2026-05-18
### Packages: GitHub installer runtime path
**Fixes**
- Fixed GitHub Releases package installs on bare-metal gateways by defaulting the GitHub binary directory to `{runtimeDir}/bin` instead of Docker-only `/app/data/.runtime/bin`.
- The fix covers installs such as `github:nextlevelbuilder/goclaw-cli@v0.4.1` on the VPS, where `/app` is not writable or present.
**Tests**
- Added default-path regression coverage and made Unix-socket apk helper tests skip cleanly on Windows environments that cannot bind Unix sockets.
---
### Providers: ChatGPT OAuth GPT-5.5 default
**Changed**
+4
View File
@@ -6,6 +6,7 @@ import (
"encoding/json"
"fmt"
"net"
"runtime"
"strings"
"sync/atomic"
"testing"
@@ -42,6 +43,9 @@ func servePkgHelper(t *testing.T, sockPath, respJSON string) func() {
ln, err := net.Listen("unix", sockPath)
if err != nil {
if runtime.GOOS == "windows" {
t.Skipf("unix sockets are not available in this Windows test environment: %v", err)
}
t.Fatalf("servePkgHelper: listen %q: %v", sockPath, err)
}
+2 -2
View File
@@ -57,7 +57,7 @@ func ParseGitHubSpec(s string) (*GitHubSpec, error) {
// Token is sourced from env var only (never config.json plaintext).
type GitHubPackagesConfig struct {
Token string // optional GitHub personal access token
BinDir string // where to install binaries (default /app/data/.runtime/bin)
BinDir string // where to install binaries (default {runtimeDir}/bin)
ManifestPath string // manifest file path (default {BinDir}/../github-packages.json)
AllowedOrgs []string // lowercase list; empty = all allowed
MaxAssetSizeMB int // default 200
@@ -66,7 +66,7 @@ type GitHubPackagesConfig struct {
// Defaults fills in zero-valued fields.
func (c *GitHubPackagesConfig) Defaults() {
if c.BinDir == "" {
c.BinDir = "/app/data/.runtime/bin"
c.BinDir = filepath.Join(packageRuntimeDir(), "bin")
}
if c.ManifestPath == "" {
c.ManifestPath = filepath.Join(filepath.Dir(c.BinDir), "github-packages.json")
+15 -5
View File
@@ -2,17 +2,18 @@ package skills
import (
"errors"
"path/filepath"
"strings"
"testing"
)
func TestParseGitHubSpec(t *testing.T) {
cases := []struct {
in string
ok bool
owner string
repo string
tag string
in string
ok bool
owner string
repo string
tag string
}{
{"github:cli/cli@v2.45.0", true, "cli", "cli", "v2.45.0"},
{"github:cli/cli", true, "cli", "cli", ""},
@@ -123,11 +124,20 @@ func TestAllowedOrg(t *testing.T) {
}
func TestConfigDefaults(t *testing.T) {
runtimeDir := t.TempDir()
t.Setenv("RUNTIME_DIR", runtimeDir)
c := &GitHubPackagesConfig{}
c.Defaults()
if c.BinDir == "" || c.ManifestPath == "" || c.MaxAssetSizeMB != 200 {
t.Errorf("unexpected defaults: %+v", c)
}
if want := filepath.Join(runtimeDir, "bin"); c.BinDir != want {
t.Errorf("BinDir = %q, want %q", c.BinDir, want)
}
if want := filepath.Join(runtimeDir, "github-packages.json"); c.ManifestPath != want {
t.Errorf("ManifestPath = %q, want %q", c.ManifestPath, want)
}
if c.MaxAssetBytes() != 200*1024*1024 {
t.Errorf("MaxAssetBytes wrong: %d", c.MaxAssetBytes())
}
+2 -1
View File
@@ -4,6 +4,7 @@ import (
"context"
"os"
"os/exec"
"path/filepath"
"strings"
"time"
)
@@ -65,7 +66,7 @@ func CheckRuntimes() *RuntimeStatus {
// Check github-bin runtime directory (where GitHub-installed binaries live).
ghInfo := RuntimeInfo{Name: "github-bin"}
binDir := "/app/data/.runtime/bin"
binDir := filepath.Join(packageRuntimeDir(), "bin")
if gh := DefaultGitHubInstaller(); gh != nil && gh.Config != nil && gh.Config.BinDir != "" {
binDir = gh.Config.BinDir
}