diff --git a/.tangled/workflows/release-credential-helper.yml b/.tangled/workflows/release-credential-helper.yml new file mode 100644 index 0000000..fedf229 --- /dev/null +++ b/.tangled/workflows/release-credential-helper.yml @@ -0,0 +1,137 @@ +# Tangled Workflow: Release Credential Helper to Tangled.org +# +# This workflow builds the docker-credential-atcr binary and publishes it +# to Tangled.org for distribution via Homebrew. +# +# Current limitation: Tangled doesn't support triggering on tags yet, +# so this triggers on push to main. Manually verify you've tagged the +# release before pushing. + +when: + - event: ["manual"] + branch: ["main"] + +engine: "nixery" + +dependencies: + nixpkgs: + - go_1_24 # Go 1.24+ for building + - git # For finding tags + - goreleaser # For building multi-platform binaries + # - goat # TODO: Add goat CLI for uploading to Tangled (if available in nixpkgs) + +environment: + CGO_ENABLED: "0" # Build static binaries + +steps: + - name: Find latest git tag + command: | + # Get the most recent version tag + LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.1") + echo "Latest tag: $LATEST_TAG" + echo "$LATEST_TAG" > .version + + # Also get the commit hash for reference + COMMIT_HASH=$(git rev-parse HEAD) + echo "Commit: $COMMIT_HASH" + + - name: Build binaries with GoReleaser + command: | + # Read version from previous step + VERSION=$(cat .version) + export VERSION + + # Build for all platforms using GoReleaser + # This creates artifacts in dist/ directory + goreleaser build --clean --snapshot --config .goreleaser.yaml + + # List what was built + echo "Built artifacts:" + ls -lh dist/ + + - name: Package artifacts + command: | + VERSION=$(cat .version) + VERSION_NO_V=${VERSION#v} # Remove 'v' prefix for filenames + + cd dist + + # Create tarballs for each platform (GoReleaser might already do this) + # Darwin x86_64 + if [ -d "docker-credential-atcr_darwin_amd64_v1" ]; then + tar czf "docker-credential-atcr_${VERSION_NO_V}_Darwin_x86_64.tar.gz" \ + -C docker-credential-atcr_darwin_amd64_v1 docker-credential-atcr + fi + + # Darwin arm64 + if [ -d "docker-credential-atcr_darwin_arm64" ]; then + tar czf "docker-credential-atcr_${VERSION_NO_V}_Darwin_arm64.tar.gz" \ + -C docker-credential-atcr_darwin_arm64 docker-credential-atcr + fi + + # Linux x86_64 + if [ -d "docker-credential-atcr_linux_amd64_v1" ]; then + tar czf "docker-credential-atcr_${VERSION_NO_V}_Linux_x86_64.tar.gz" \ + -C docker-credential-atcr_linux_amd64_v1 docker-credential-atcr + fi + + # Linux arm64 + if [ -d "docker-credential-atcr_linux_arm64" ]; then + tar czf "docker-credential-atcr_${VERSION_NO_V}_Linux_arm64.tar.gz" \ + -C docker-credential-atcr_linux_arm64 docker-credential-atcr + fi + + echo "Created tarballs:" + ls -lh *.tar.gz + + - name: Upload to Tangled.org + command: | + VERSION=$(cat .version) + VERSION_NO_V=${VERSION#v} + + # TODO: Authenticate with goat CLI + # You'll need to set up credentials/tokens for goat + # Example (adjust based on goat's actual auth mechanism): + # goat login --pds https://your-pds.example.com --handle your.handle + + # TODO: Upload each artifact to Tangled.org + # This creates sh.tangled.repo.artifact records in your ATProto PDS + # Adjust these commands based on scripts/publish-artifact.sh pattern + + # Example structure (you'll need to fill in actual goat commands): + # for artifact in dist/*.tar.gz; do + # echo "Uploading $artifact..." + # goat upload \ + # --repo "at-container-registry" \ + # --tag "$VERSION" \ + # --file "$artifact" + # done + + echo "TODO: Implement goat upload commands" + echo "See scripts/publish-artifact.sh for reference" + echo "" + echo "After uploading, you'll receive a TAG_HASH from Tangled." + echo "Update Formula/docker-credential-atcr.rb with:" + echo " VERSION = \"$VERSION_NO_V\"" + echo " TAG_HASH = \"\"" + echo "" + echo "Then run: scripts/update-homebrew-formula.sh $VERSION_NO_V " + + - name: Generate checksums for verification + command: | + VERSION=$(cat .version) + VERSION_NO_V=${VERSION#v} + + cd dist + + echo "SHA256 checksums for Homebrew formula:" + echo "=======================================" + + for file in docker-credential-atcr_${VERSION_NO_V}_*.tar.gz; do + if [ -f "$file" ]; then + sha256sum "$file" + fi + done + + echo "" + echo "Copy these checksums to Formula/docker-credential-atcr.rb" diff --git a/Formula/docker-credential-atcr.rb b/Formula/docker-credential-atcr.rb new file mode 100644 index 0000000..8911c36 --- /dev/null +++ b/Formula/docker-credential-atcr.rb @@ -0,0 +1,54 @@ +# typed: false +# frozen_string_literal: true + +class DockerCredentialAtcr < Formula + desc "Docker credential helper for ATCR (ATProto Container Registry)" + homepage "https://atcr.io" + url "https://github.com/atcr-io/atcr/archive/refs/tags/v0.0.1.tar.gz" + sha256 "REPLACE_WITH_TARBALL_SHA256" + license "MIT" + head "https://github.com/atcr-io/atcr.git", branch: "main" + + depends_on "go" => :build + + def install + # Build the credential helper binary + # Use ldflags to inject version information + ldflags = %W[ + -s -w + -X main.version=#{version} + -X main.commit=#{tap.user} + -X main.date=#{time.iso8601} + ] + + system "go", "build", *std_go_args(ldflags:, output: bin/"docker-credential-atcr"), "./cmd/credential-helper" + end + + test do + # Test that the binary exists and is executable + assert_match version.to_s, shell_output("#{bin}/docker-credential-atcr version 2>&1") + end + + def caveats + <<~EOS + To configure Docker to use ATCR credential helper, add the following + to your ~/.docker/config.json: + + { + "credHelpers": { + "atcr.io": "atcr" + } + } + + Note: The credential helper name is "atcr" (Docker automatically prefixes + with "docker-credential-" when looking for the binary). + + To authenticate with ATCR: + docker push atcr.io//:latest + + This will open your browser to complete the OAuth device flow. + + Configuration is stored in: ~/.atcr/device.json + EOS + end +end diff --git a/INSTALLATION.md b/INSTALLATION.md index 32d78f4..8038d70 100644 --- a/INSTALLATION.md +++ b/INSTALLATION.md @@ -37,13 +37,22 @@ Invoke-WebRequest -Uri https://atcr.io/install.ps1 -OutFile install.ps1 .\install.ps1 ``` -### Using Homebrew (macOS) -You can read the full manifest spec here, but the dependencies block is the real interesting bit. Dependencies for your workflow, like Go, Node.js, Python etc. can be pulled in from nixpkgs. Nixpkgs—for the uninitiated—is a vast collection of packages for the Nix package manager. Fortunately, you needn’t know nor care about Nix to use it! Just head to https://search.nixos.org to find your package of choice (I’ll bet 1€ that it’s there1), toss it in the list and run your build. The Nix-savvy of you lot will be happy to know that you can use custom registries too. +### Using Homebrew (macOS and Linux) + ```bash +# Add the ATCR tap brew tap atcr-io/tap + +# Install the credential helper brew install docker-credential-atcr ``` +The Homebrew formula supports: +- **macOS**: Intel (x86_64) and Apple Silicon (arm64) +- **Linux**: x86_64 and arm64 + +Homebrew will automatically download the correct binary for your platform. + ### Manual Installation 1. **Download the binary** for your platform from [GitHub Releases](https://github.com/atcr-io/atcr/releases) diff --git a/license b/license new file mode 100644 index 0000000..e88b779 --- /dev/null +++ b/license @@ -0,0 +1,25 @@ +The MIT License (MIT) +===================== + +Copyright © 2025 Evan Jarrett + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the “Software”), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/scripts/update-homebrew-formula.sh b/scripts/update-homebrew-formula.sh new file mode 100755 index 0000000..356c60c --- /dev/null +++ b/scripts/update-homebrew-formula.sh @@ -0,0 +1,110 @@ +#!/usr/bin/env bash +# +# update-homebrew-formula.sh - Helper script to update Homebrew formula with new release +# +# Usage: ./scripts/update-homebrew-formula.sh +# +# Example: ./scripts/update-homebrew-formula.sh v0.0.2 +# +# This script: +# 1. Downloads the source tarball from GitHub +# 2. Calculates SHA256 checksum +# 3. Generates updated formula snippet +# + +set -euo pipefail + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Check arguments +if [ $# -ne 1 ]; then + echo -e "${RED}Error: Missing required argument${NC}" + echo "Usage: $0 " + echo "" + echo "Example: $0 v0.0.2" + echo " $0 0.0.2 (v prefix is optional)" + exit 1 +fi + +VERSION="$1" + +# Add 'v' prefix if not present +if [[ ! "$VERSION" =~ ^v ]]; then + VERSION="v${VERSION}" +fi + +echo -e "${GREEN}Updating Homebrew formula for version ${VERSION}${NC}" +echo "" + +# GitHub repository details +GITHUB_REPO="atcr-io/atcr" +TARBALL_URL="https://github.com/${GITHUB_REPO}/archive/refs/tags/${VERSION}.tar.gz" + +# Create temporary directory +TEMP_DIR=$(mktemp -d) +trap 'rm -rf "$TEMP_DIR"' EXIT + +TARBALL_FILE="${TEMP_DIR}/${VERSION}.tar.gz" + +echo -e "${YELLOW}Downloading source tarball...${NC}" +echo "URL: ${TARBALL_URL}" + +if curl -sSfL -o "$TARBALL_FILE" "$TARBALL_URL"; then + # Calculate SHA256 + if command -v sha256sum &> /dev/null; then + CHECKSUM=$(sha256sum "$TARBALL_FILE" | awk '{print $1}') + elif command -v shasum &> /dev/null; then + CHECKSUM=$(shasum -a 256 "$TARBALL_FILE" | awk '{print $1}') + else + echo -e "${RED}Error: sha256sum or shasum command not found${NC}" + exit 1 + fi + + echo -e "${GREEN}✓ Downloaded successfully${NC}" + echo "SHA256: $CHECKSUM" +else + echo -e "${RED}✗ Failed to download source tarball${NC}" + echo "" + echo "Make sure the tag ${VERSION} exists on GitHub:" + echo " https://github.com/${GITHUB_REPO}/releases/tag/${VERSION}" + echo "" + echo "If you haven't pushed the tag yet, run:" + echo " git tag ${VERSION}" + echo " git push origin ${VERSION}" + exit 1 +fi + +echo "" +echo "======================================================================" +echo "Copy the following to Formula/docker-credential-atcr.rb:" +echo "======================================================================" +echo "" + +cat << EOF + url "https://github.com/${GITHUB_REPO}/archive/refs/tags/${VERSION}.tar.gz" + sha256 "${CHECKSUM}" + license "MIT" + head "https://github.com/${GITHUB_REPO}.git", branch: "main" +EOF + +echo "" +echo "======================================================================" +echo "" +echo -e "${YELLOW}Next steps:${NC}" +echo "1. Update Formula/docker-credential-atcr.rb with the url and sha256 above" +echo "2. Test the formula locally:" +echo " brew install --build-from-source Formula/docker-credential-atcr.rb" +echo " docker-credential-atcr version" +echo "3. Commit and push to your atcr-io/homebrew-tap repository:" +echo " cd /path/to/homebrew-tap" +echo " cp Formula/docker-credential-atcr.rb ." +echo " git add docker-credential-atcr.rb" +echo " git commit -m \"Update docker-credential-atcr to ${VERSION}\"" +echo " git push" +echo "4. Users can upgrade with:" +echo " brew update" +echo " brew upgrade docker-credential-atcr"