Files
gh-flox-flox-agentic-flox-p…/skills/flox-publish/SKILL.md
2025-11-29 18:27:20 +08:00

482 lines
11 KiB
Markdown

---
name: flox-publish
description: Use for publishing user packages to flox for use in Flox environments. Use for package distribution and sharing of builds defined in a flox environment.
---
# Flox Package Publishing Guide
## Core Commands
```bash
flox publish # Publish all packages
flox publish my_package # Publish single package
flox publish -o myorg package # Publish to organization
flox publish -o myuser package # Publish to personal namespace
flox auth login # Authenticate before publishing
```
## Publishing Workflow: Development to Runtime
Publishing packages enables a clear separation between **development** and **runtime/consumption**:
### The Complete Workflow
**Phase 1: Development Environment**
```toml
# .flox/env/manifest.toml (in git with source code)
[install]
gcc.pkg-path = "gcc13"
make.pkg-path = "make"
python.pkg-path = "python311Full"
[build.myapp]
command = '''
python setup.py build
mkdir -p $out/bin
cp build/myapp $out/bin/
'''
version = "1.0.0"
```
Developers work in this environment, commit `.flox/` to git alongside source code.
**Phase 2: Build and Publish**
```bash
# Build the package
flox build myapp
# Publish to catalog
flox publish -o myorg myapp
```
The published package contains BINARIES/ARTIFACTS (what's in `$out/`), NOT source code.
**Phase 3: Runtime Environment**
```toml
# Separate environment (can be pushed to FloxHub)
[install]
myapp.pkg-path = "myorg/myapp" # The published package
```
Consumers create runtime environments and install the published package. No build tools needed, no source code exposed.
**Key insight**: You don't install the published package back into the development environment - that would be circular. Published packages are installed into OTHER environments (different projects, production, etc.).
## Publishing to Flox Catalog
### Prerequisites
Before publishing:
- Package defined in `[build]` section or `.flox/pkgs/`
- Environment in Git repo with configured remote
- Clean working tree (no uncommitted changes)
- Current commit pushed to remote
- All build files tracked by Git
- At least one package installed in `[install]`
### Authentication
Run authentication before first publish:
```bash
flox auth login
```
### Publishing Commands
```bash
# Publish single package
flox publish my_package
# Publish all packages
flox publish
# Publish to organization
flox publish -o myorg my_package
# Publish to personal namespace (for testing)
flox publish -o mypersonalhandle my_package
```
### Catalog Types
**Personal catalogs**: Only visible to you (good for testing)
- Published to your personal namespace
- Example: User "alice" publishes "hello" → available as `alice/hello`
- Useful for testing before publishing to organization
**Organization catalogs**: Shared with team members (paid feature)
- Published to organization namespace
- Example: Org "acme" publishes "tool" → available as `acme/tool`
- All organization members can install
### Build Validation
Flox clones your repo to a temp location and performs a clean build to ensure reproducibility. Only packages that build successfully in this clean environment can be published.
This validation ensures:
- All dependencies are declared
- Build is reproducible
- No reliance on local machine state
- Git repository is clean and up-to-date
### After Publishing
- Package available in `flox search`, `flox show`, `flox install`
- Metadata sent to Flox servers
- Package binaries uploaded to Catalog Store
- Install with: `flox install <catalog>/<package>`
Users can then:
```bash
# Search for your package
flox search my_package
# See package details
flox show myorg/my_package
# Install the package
flox install myorg/my_package
```
### What Gets Published
**Published packages contain:**
- Binaries and compiled artifacts (everything in `$out/`)
- Runtime dependencies specified in `runtime-packages`
- Package metadata (version, description)
**Published packages do NOT contain:**
- Source code (unless explicitly copied to `$out/`)
- Build tools or build-time dependencies
- Development environment configuration
- The `.flox/` directory itself
This separation allows you to share built artifacts without exposing source code.
## Real-world Publishing Workflows
### Application Development Workflow
**Developer workflow:**
1. Create development environment with build tools:
```bash
mkdir myapp && cd myapp
flox init
flox install gcc make python311Full
```
2. Add source code and build definition to `.flox/env/manifest.toml`:
```toml
[build.myapp]
command = '''make && cp myapp $out/bin/'''
version = "1.0.0"
```
3. Commit to git (environment definition + source code):
```bash
git add .flox/ src/
git commit -m "Add development environment and source"
git push origin main
```
4. Build and publish package (binaries/artifacts):
```bash
flox build myapp
flox publish -o myorg myapp
```
**Other developers:**
- Clone repo: `git clone <repo> && cd myapp && flox activate`
- Get the same development environment with build tools
**Consumers:**
- Create new runtime environment: `flox init && flox install myorg/myapp`
- OR install into existing environment: `flox install myorg/myapp`
- Get the BUILT package (binaries), not source code
- Can push runtime environment to FloxHub without exposing source
### Fork-based Development Pattern
1. Fork upstream repo (e.g., `user/project` from `upstream/project`)
2. Add `.flox/` to fork with build definitions
3. Commit and push: `git push origin main`
4. Publish package: `flox publish -o username package-name`
5. Others can install: `flox install username/package-name`
## Versioning Strategies
### Semantic Versioning
```toml
[build.mytool]
version = "1.2.3" # Major.Minor.Patch
description = "My awesome tool"
```
### Git-based Versioning
```toml
[build.mytool]
version.command = "git describe --tags"
description = "My awesome tool"
```
### File-based Versioning
```toml
[build.mytool]
version.file = "VERSION.txt"
description = "My awesome tool"
```
### Dynamic Versioning from Source
```toml
[build.rustapp]
version.command = "cargo metadata --no-deps --format-version 1 | jq -r '.packages[0].version'"
```
## Publishing Multiple Variants
You can publish multiple variants of the same project:
```toml
[build.myapp]
command = '''
cargo build --release
mkdir -p $out/bin
cp target/release/myapp $out/bin/
'''
version = "1.0.0"
description = "Production build"
sandbox = "pure"
[build.myapp-debug]
command = '''
cargo build
mkdir -p $out/bin
cp target/debug/myapp $out/bin/myapp-debug
'''
version = "1.0.0"
description = "Debug build with symbols"
sandbox = "off"
```
Both can be published and users can choose which to install.
## Testing Before Publishing
### Local Testing
1. Build the package:
```bash
flox build myapp
```
2. Test the built artifact:
```bash
./result-myapp/bin/myapp --version
```
3. Install locally to test:
```bash
flox install ./result-myapp
```
### Personal Catalog Testing
Publish to your personal namespace first:
```bash
flox publish -o myusername myapp
```
Then test installation:
```bash
flox install myusername/myapp
```
Once validated, republish to organization:
```bash
flox publish -o myorg myapp
```
## Common Gotchas
### Branch names
Many repos use `master` not `main` - check with `git branch`
### Auth required
Run `flox auth login` before first publish
### Clean git state
Commit and push ALL changes before `flox publish`:
```bash
git status # Check for uncommitted changes
git add .flox/
git commit -m "Add flox build configuration"
git push origin master
```
### runtime-packages
List only what package needs at runtime, not build deps:
```toml
[install]
gcc.pkg-path = "gcc"
make.pkg-path = "make"
[build.myapp]
command = '''make && cp myapp $out/bin/'''
runtime-packages = [] # No runtime deps needed
```
### Git-tracked files only
All files referenced in build must be tracked:
```bash
git add .flox/pkgs/*
git add src/
git commit -m "Add build files"
```
## Publishing Nix Expression Builds
For Nix expression builds in `.flox/pkgs/`:
1. Create the Nix expression:
```bash
mkdir -p .flox/pkgs
cat > .flox/pkgs/hello.nix << 'EOF'
{ hello }:
hello.overrideAttrs (oldAttrs: {
patches = (oldAttrs.patches or []) ++ [ ./my.patch ];
})
EOF
```
2. Track with Git:
```bash
git add .flox/pkgs/*
git commit -m "Add hello package"
git push
```
3. Publish:
```bash
flox publish hello
```
## Publishing Configuration and Assets
You can publish non-code artifacts:
### Configuration templates
```toml
[build.nginx-config]
command = '''
mkdir -p $out/etc
cp nginx.conf $out/etc/
cp -r conf.d $out/etc/
'''
version = "1.0.0"
description = "Organization Nginx configuration"
```
### Protocol buffers
```toml
[build.api-proto]
command = '''
mkdir -p $out/share/proto
cp proto/**/*.proto $out/share/proto/
'''
version = "2.1.0"
description = "API protocol definitions"
```
Teams install and reference via `$FLOX_ENV/etc/` or `$FLOX_ENV/share/`.
## Continuous Integration Publishing
### GitHub Actions Example
```yaml
name: Publish to Flox
on:
push:
tags:
- 'v*'
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Flox
run: |
curl -fsSL https://downloads.flox.dev/by-env/stable/install | bash
- name: Authenticate
env:
FLOX_AUTH_TOKEN: ${{ secrets.FLOX_AUTH_TOKEN }}
run: flox auth login --token "$FLOX_AUTH_TOKEN"
- name: Publish package
run: flox publish -o myorg mypackage
```
### GitLab CI Example
```yaml
publish:
stage: deploy
only:
- tags
script:
- curl -fsSL https://downloads.flox.dev/by-env/stable/install | bash
- flox auth login --token "$FLOX_AUTH_TOKEN"
- flox publish -o myorg mypackage
```
## Package Metadata Best Practices
### Good Descriptions
```toml
[build.cli]
description = "High-performance log shipper with filtering" # Good: specific, descriptive
# Avoid:
# description = "My tool" # Too vague
# description = "CLI" # Not descriptive enough
```
### Proper Versioning
- Use semantic versioning: MAJOR.MINOR.PATCH
- Increment MAJOR for breaking changes
- Increment MINOR for new features
- Increment PATCH for bug fixes
### Runtime Dependencies
Only include what's actually needed at runtime:
```toml
[install]
# Build-time only
gcc.pkg-path = "gcc"
make.pkg-path = "make"
# Runtime dependency
libssl.pkg-path = "openssl"
[build.myapp]
runtime-packages = ["libssl"] # Only runtime deps
```
## Related Skills
- **flox-builds** - Building packages before publishing, dual-environment workflow
- **flox-environments** - Setting up development and runtime environments
- **flox-sharing** - Sharing environment definitions (via git or FloxHub) vs publishing packages (binaries/artifacts)