Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
7 changes: 5 additions & 2 deletions .bin/b.yaml
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
b:
jq:

binaries:
jq:
version: jq-1.7
kubectl: {}
2 changes: 1 addition & 1 deletion .envrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
# Template form:
# https://github.com/arg-sh/argsh
# https://github.com/fentas/b
# curl -sfLS https://envrc.arg.sh > .envrc
# This is an example of a .envrc file for use with direnv.
# It sets up the environment for the project.
Expand Down
67 changes: 67 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: Deploy Documentation

on:
push:
branches: [ main ]
paths:
- 'www/apps/docs/**'
- '.github/workflows/docs.yml'
pull_request:
branches: [ main ]
paths:
- 'www/apps/docs/**'

permissions:
contents: read
pages: write
id-token: write

concurrency:
group: "pages"
cancel-in-progress: false

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'yarn'
cache-dependency-path: www/yarn.lock

- name: Install dependencies
run: |
cd www
yarn install

- name: Build Docusaurus site
run: |
cd www
yarn run build

- name: Setup Pages
if: github.ref == 'refs/heads/main'
uses: actions/configure-pages@v4

- name: Upload artifact
if: github.ref == 'refs/heads/main'
uses: actions/upload-pages-artifact@v3
with:
path: www/apps/docs/build

deploy:
if: github.ref == 'refs/heads/main'
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,12 @@ If none of these are set, `b` will fail.
To properly use the `--all` flag, you should create a `b.yaml` file in the binary directory. This file should contain a list of binaries you want to manage. Here is an example:

```yaml
jq:
# pin version
version: jq-1.8.1
kind:
tilt:
binaries:
jq:
# pin version
version: jq-1.8.1
kind:
tilt:
```

This will ensure that `jq`, `kind`, and `tilt` are installed and at the correct version. If you don't specify a version, `b` will install the latest version.
Expand Down Expand Up @@ -119,7 +120,7 @@ Have a look at [pkg/binary](./pkg/binary/) for more details.

Have a look at [pkg/binaries](./pkg/binaries/) for prepackaged binaries.

- [argsh](https://github.com/arg-sh/argsh) - Utilities for Bash script quality
- [argsh](https://github.com/fentas/b) - Utilities for Bash script quality
- `b` - (Selfupdate) Manage and execute binary files
- [cilium](https://github.com/cilium/cilium-cli) - Providing, securing, and observing network connectivity between workloads
- [clusterctl](https://github.com/kubernetes-sigs/cluster-api) - Kubernetes cluster lifecycle management
Expand Down
6 changes: 6 additions & 0 deletions logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion pkg/binaries/argsh/argsh.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func Binary(options *binaries.BinaryOptions) *binary.Binary {
Tracker: options.Tracker,
Version: options.Version,
Name: "argsh",
GitHubRepo: "arg-sh/argsh",
GitHubRepo: "fentas/b",
GitHubFile: "argsh",
VersionF: binary.GithubLatest,
VersionLocalF: func(b *binary.Binary) (string, error) {
Expand Down
4 changes: 2 additions & 2 deletions pkg/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type CmdBinaryOptions struct {
IO *streams.IO
Binaries []*binary.Binary
NoConfig bool
config *state.BinaryList
config *state.State

// Flags
all bool
Expand Down Expand Up @@ -152,7 +152,7 @@ func (o *CmdBinaryOptions) Complete(cmd *cobra.Command, args []string) error {
}

if o.config != nil {
for _, lb := range *o.config {
for _, lb := range o.config.Binaries {
for b, do := range o.ensure {
if lb.Name == b.Name {
b.Version = lb.Version
Expand Down
11 changes: 1 addition & 10 deletions pkg/cli/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"github.com/fentas/goodies/templates"
"github.com/spf13/cobra"

"github.com/fentas/b/pkg/binary"
"github.com/fentas/b/pkg/path"
"github.com/fentas/b/pkg/state"
)
Expand Down Expand Up @@ -96,15 +95,7 @@ func (o *InitOptions) createConfigWithSelfReference(configPath string) error {
if err := os.MkdirAll(dir, 0755); err != nil {
return err
}

// Create config with self-reference to 'b'
config := &state.BinaryList{
&binary.LocalBinary{
Name: "b",
},
}

return state.SaveConfig(config, configPath)
return state.CreateDefaultConfig(configPath)
}

// createProjectFiles creates additional project files (.gitignore, .envrc) if needed
Expand Down
10 changes: 5 additions & 5 deletions pkg/cli/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,20 +187,20 @@ func (o *InstallOptions) addToConfig(binaries []*binary.Binary) error {
// Load existing config or create new one
config := o.Config
if config == nil {
config = &state.BinaryList{}
config = &state.State{}
}

// Add binaries to config
for _, b := range binaries {
// Check if already exists
found := false
for i, existing := range *config {
for i, existing := range config.Binaries {
if existing.Name == b.Name {
// Update version only if we have a specific version
if b.Version != "" && b.Version != "latest" {
(*config)[i].Version = b.Version
config.Binaries[i].Version = b.Version
if o.Fix {
(*config)[i].Enforced = b.Version
config.Binaries[i].Enforced = b.Version
}
}
found = true
Expand All @@ -219,7 +219,7 @@ func (o *InstallOptions) addToConfig(binaries []*binary.Binary) error {
entry.Enforced = b.Version
}
}
*config = append(*config, entry)
config.Binaries = append(config.Binaries, entry)
}
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/cli/shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
type SharedOptions struct {
IO *streams.IO
Binaries []*binary.Binary
Config *state.BinaryList
Config *state.State

// Global flags
ConfigPath string
Expand Down Expand Up @@ -75,7 +75,7 @@ func (o *SharedOptions) GetBinariesFromConfig() []*binary.Binary {
}

var result []*binary.Binary
for _, lb := range *o.Config {
for _, lb := range o.Config.Binaries {
if b, ok := o.lookup[lb.Name]; ok {
// Set version from config
b.Version = lb.Version
Expand Down
22 changes: 13 additions & 9 deletions pkg/cli/version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func TestVersionOptions_Validate(t *testing.T) {
func TestVersionOptions_Run(t *testing.T) {
tests := []struct {
name string
config *state.BinaryList
config *state.State
local bool
check bool
quiet bool
Expand All @@ -106,10 +106,12 @@ func TestVersionOptions_Run(t *testing.T) {
}{
{
name: "run with config",
config: &state.BinaryList{
&binary.LocalBinary{
Name: "jq",
Version: "1.7",
config: &state.State{
Binaries: state.BinaryList{
&binary.LocalBinary{
Name: "jq",
Version: "1.7",
},
},
},
local: false,
Expand All @@ -118,10 +120,12 @@ func TestVersionOptions_Run(t *testing.T) {
},
{
name: "run local only",
config: &state.BinaryList{
&binary.LocalBinary{
Name: "jq",
Version: "1.7",
config: &state.State{
Binaries: state.BinaryList{
&binary.LocalBinary{
Name: "jq",
Version: "1.7",
},
},
},
local: true,
Expand Down
20 changes: 11 additions & 9 deletions pkg/state/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
)

// LoadConfigFromPath loads configuration from a specific path
func LoadConfigFromPath(configPath string) (*BinaryList, error) {
func LoadConfigFromPath(configPath string) (*State, error) {
if _, err := os.Stat(configPath); err != nil {
return nil, err
}
Expand All @@ -20,16 +20,16 @@ func LoadConfigFromPath(configPath string) (*BinaryList, error) {
return nil, err
}

var list BinaryList
if err := yaml.Unmarshal(config, &list); err != nil {
var state State
if err := yaml.Unmarshal(config, &state); err != nil {
return nil, err
}

return &list, nil
return &state, nil
}

// LoadConfig loads configuration with automatic discovery
func LoadConfig() (*BinaryList, error) {
func LoadConfig() (*State, error) {
configPath, err := path.FindConfigFile()
if err != nil {
return nil, err
Expand All @@ -43,7 +43,7 @@ func LoadConfig() (*BinaryList, error) {
}

// SaveConfig saves the configuration to the specified path
func SaveConfig(config *BinaryList, configPath string) error {
func SaveConfig(config *State, configPath string) error {
// Ensure directory exists
dir := filepath.Dir(configPath)
if err := os.MkdirAll(dir, 0755); err != nil {
Expand All @@ -60,9 +60,11 @@ func SaveConfig(config *BinaryList, configPath string) error {

// CreateDefaultConfig creates a default b.yaml configuration file
func CreateDefaultConfig(configPath string) error {
defaultConfig := BinaryList{
&binary.LocalBinary{
Name: "b",
defaultConfig := State{
Binaries: BinaryList{
&binary.LocalBinary{
Name: "b",
},
},
}
return SaveConfig(&defaultConfig, configPath)
Expand Down
39 changes: 33 additions & 6 deletions pkg/state/types.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,39 @@
// Package state provides state management for b
package state

import (
"github.com/fentas/b/pkg/binary"
)

type State struct {
Binaries BinaryList `yaml:"binaries"`
}

// MarshalYAML implements the yaml.Marshaler interface for State
func (s *State) MarshalYAML() (interface{}, error) {
binaries, err := s.Binaries.MarshalYAML()
if err != nil {
return nil, err
}

return map[string]interface{}{
"binaries": binaries,
}, nil
}

// UnmarshalYAML implements the yaml.Unmarshaler interface for State
func (s *State) UnmarshalYAML(unmarshal func(interface{}) error) error {
type Alias State
var aux Alias

if err := unmarshal(&aux); err != nil {
return err
}

*s = State(aux)
return nil
}

type BinaryList []*binary.LocalBinary

func (list *BinaryList) UnmarshalYAML(unmarshal func(interface{}) error) error {
Expand All @@ -27,15 +57,12 @@ func (list *BinaryList) MarshalYAML() (interface{}, error) {
result := make(map[string]interface{})
for _, b := range *list {
if b.Name != "" {
// Only include version if it's set and not empty
if b.Version != "" && b.Version != "latest" {
// Create a simple map with only the version field
if b.Enforced != "" {
result[b.Name] = map[string]string{
"version": b.Version,
"version": b.Enforced,
}
} else {
// Just the key with no value (null)
result[b.Name] = nil
result[b.Name] = &struct{}{}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion test/TESTING_PLAN.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Testing Plan for B CLI Tool
# Testing Plan for b CLI Tool

## Overview

Expand Down
Loading
Loading