A container registry that uses the AT Protocol for manifest storage and S3 for blob storage. atcr.io
docker container atproto go

begin brew tap support

evan.jarrett.net 6b56f187 e296971c

verified
+137
.tangled/workflows/release-credential-helper.yml
··· 1 + # Tangled Workflow: Release Credential Helper to Tangled.org 2 + # 3 + # This workflow builds the docker-credential-atcr binary and publishes it 4 + # to Tangled.org for distribution via Homebrew. 5 + # 6 + # Current limitation: Tangled doesn't support triggering on tags yet, 7 + # so this triggers on push to main. Manually verify you've tagged the 8 + # release before pushing. 9 + 10 + when: 11 + - event: ["manual"] 12 + branch: ["main"] 13 + 14 + engine: "nixery" 15 + 16 + dependencies: 17 + nixpkgs: 18 + - go_1_24 # Go 1.24+ for building 19 + - git # For finding tags 20 + - goreleaser # For building multi-platform binaries 21 + # - goat # TODO: Add goat CLI for uploading to Tangled (if available in nixpkgs) 22 + 23 + environment: 24 + CGO_ENABLED: "0" # Build static binaries 25 + 26 + steps: 27 + - name: Find latest git tag 28 + command: | 29 + # Get the most recent version tag 30 + LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.1") 31 + echo "Latest tag: $LATEST_TAG" 32 + echo "$LATEST_TAG" > .version 33 + 34 + # Also get the commit hash for reference 35 + COMMIT_HASH=$(git rev-parse HEAD) 36 + echo "Commit: $COMMIT_HASH" 37 + 38 + - name: Build binaries with GoReleaser 39 + command: | 40 + # Read version from previous step 41 + VERSION=$(cat .version) 42 + export VERSION 43 + 44 + # Build for all platforms using GoReleaser 45 + # This creates artifacts in dist/ directory 46 + goreleaser build --clean --snapshot --config .goreleaser.yaml 47 + 48 + # List what was built 49 + echo "Built artifacts:" 50 + ls -lh dist/ 51 + 52 + - name: Package artifacts 53 + command: | 54 + VERSION=$(cat .version) 55 + VERSION_NO_V=${VERSION#v} # Remove 'v' prefix for filenames 56 + 57 + cd dist 58 + 59 + # Create tarballs for each platform (GoReleaser might already do this) 60 + # Darwin x86_64 61 + if [ -d "docker-credential-atcr_darwin_amd64_v1" ]; then 62 + tar czf "docker-credential-atcr_${VERSION_NO_V}_Darwin_x86_64.tar.gz" \ 63 + -C docker-credential-atcr_darwin_amd64_v1 docker-credential-atcr 64 + fi 65 + 66 + # Darwin arm64 67 + if [ -d "docker-credential-atcr_darwin_arm64" ]; then 68 + tar czf "docker-credential-atcr_${VERSION_NO_V}_Darwin_arm64.tar.gz" \ 69 + -C docker-credential-atcr_darwin_arm64 docker-credential-atcr 70 + fi 71 + 72 + # Linux x86_64 73 + if [ -d "docker-credential-atcr_linux_amd64_v1" ]; then 74 + tar czf "docker-credential-atcr_${VERSION_NO_V}_Linux_x86_64.tar.gz" \ 75 + -C docker-credential-atcr_linux_amd64_v1 docker-credential-atcr 76 + fi 77 + 78 + # Linux arm64 79 + if [ -d "docker-credential-atcr_linux_arm64" ]; then 80 + tar czf "docker-credential-atcr_${VERSION_NO_V}_Linux_arm64.tar.gz" \ 81 + -C docker-credential-atcr_linux_arm64 docker-credential-atcr 82 + fi 83 + 84 + echo "Created tarballs:" 85 + ls -lh *.tar.gz 86 + 87 + - name: Upload to Tangled.org 88 + command: | 89 + VERSION=$(cat .version) 90 + VERSION_NO_V=${VERSION#v} 91 + 92 + # TODO: Authenticate with goat CLI 93 + # You'll need to set up credentials/tokens for goat 94 + # Example (adjust based on goat's actual auth mechanism): 95 + # goat login --pds https://your-pds.example.com --handle your.handle 96 + 97 + # TODO: Upload each artifact to Tangled.org 98 + # This creates sh.tangled.repo.artifact records in your ATProto PDS 99 + # Adjust these commands based on scripts/publish-artifact.sh pattern 100 + 101 + # Example structure (you'll need to fill in actual goat commands): 102 + # for artifact in dist/*.tar.gz; do 103 + # echo "Uploading $artifact..." 104 + # goat upload \ 105 + # --repo "at-container-registry" \ 106 + # --tag "$VERSION" \ 107 + # --file "$artifact" 108 + # done 109 + 110 + echo "TODO: Implement goat upload commands" 111 + echo "See scripts/publish-artifact.sh for reference" 112 + echo "" 113 + echo "After uploading, you'll receive a TAG_HASH from Tangled." 114 + echo "Update Formula/docker-credential-atcr.rb with:" 115 + echo " VERSION = \"$VERSION_NO_V\"" 116 + echo " TAG_HASH = \"<hash-from-tangled>\"" 117 + echo "" 118 + echo "Then run: scripts/update-homebrew-formula.sh $VERSION_NO_V <tag-hash>" 119 + 120 + - name: Generate checksums for verification 121 + command: | 122 + VERSION=$(cat .version) 123 + VERSION_NO_V=${VERSION#v} 124 + 125 + cd dist 126 + 127 + echo "SHA256 checksums for Homebrew formula:" 128 + echo "=======================================" 129 + 130 + for file in docker-credential-atcr_${VERSION_NO_V}_*.tar.gz; do 131 + if [ -f "$file" ]; then 132 + sha256sum "$file" 133 + fi 134 + done 135 + 136 + echo "" 137 + echo "Copy these checksums to Formula/docker-credential-atcr.rb"
+54
Formula/docker-credential-atcr.rb
··· 1 + # typed: false 2 + # frozen_string_literal: true 3 + 4 + class DockerCredentialAtcr < Formula 5 + desc "Docker credential helper for ATCR (ATProto Container Registry)" 6 + homepage "https://atcr.io" 7 + url "https://github.com/atcr-io/atcr/archive/refs/tags/v0.0.1.tar.gz" 8 + sha256 "REPLACE_WITH_TARBALL_SHA256" 9 + license "MIT" 10 + head "https://github.com/atcr-io/atcr.git", branch: "main" 11 + 12 + depends_on "go" => :build 13 + 14 + def install 15 + # Build the credential helper binary 16 + # Use ldflags to inject version information 17 + ldflags = %W[ 18 + -s -w 19 + -X main.version=#{version} 20 + -X main.commit=#{tap.user} 21 + -X main.date=#{time.iso8601} 22 + ] 23 + 24 + system "go", "build", *std_go_args(ldflags:, output: bin/"docker-credential-atcr"), "./cmd/credential-helper" 25 + end 26 + 27 + test do 28 + # Test that the binary exists and is executable 29 + assert_match version.to_s, shell_output("#{bin}/docker-credential-atcr version 2>&1") 30 + end 31 + 32 + def caveats 33 + <<~EOS 34 + To configure Docker to use ATCR credential helper, add the following 35 + to your ~/.docker/config.json: 36 + 37 + { 38 + "credHelpers": { 39 + "atcr.io": "atcr" 40 + } 41 + } 42 + 43 + Note: The credential helper name is "atcr" (Docker automatically prefixes 44 + with "docker-credential-" when looking for the binary). 45 + 46 + To authenticate with ATCR: 47 + docker push atcr.io/<your-handle>/<image>:latest 48 + 49 + This will open your browser to complete the OAuth device flow. 50 + 51 + Configuration is stored in: ~/.atcr/device.json 52 + EOS 53 + end 54 + end
+11 -2
INSTALLATION.md
··· 37 37 .\install.ps1 38 38 ``` 39 39 40 - ### Using Homebrew (macOS) 41 - 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. 40 + ### Using Homebrew (macOS and Linux) 41 + 42 42 ```bash 43 + # Add the ATCR tap 43 44 brew tap atcr-io/tap 45 + 46 + # Install the credential helper 44 47 brew install docker-credential-atcr 45 48 ``` 49 + 50 + The Homebrew formula supports: 51 + - **macOS**: Intel (x86_64) and Apple Silicon (arm64) 52 + - **Linux**: x86_64 and arm64 53 + 54 + Homebrew will automatically download the correct binary for your platform. 46 55 47 56 ### Manual Installation 48 57
+25
license
··· 1 + The MIT License (MIT) 2 + ===================== 3 + 4 + Copyright © 2025 Evan Jarrett 5 + 6 + Permission is hereby granted, free of charge, to any person 7 + obtaining a copy of this software and associated documentation 8 + files (the “Software”), to deal in the Software without 9 + restriction, including without limitation the rights to use, 10 + copy, modify, merge, publish, distribute, sublicense, and/or sell 11 + copies of the Software, and to permit persons to whom the 12 + Software is furnished to do so, subject to the following 13 + conditions: 14 + 15 + The above copyright notice and this permission notice shall be 16 + included in all copies or substantial portions of the Software. 17 + 18 + THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, 19 + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 + OTHER DEALINGS IN THE SOFTWARE.
+110
scripts/update-homebrew-formula.sh
··· 1 + #!/usr/bin/env bash 2 + # 3 + # update-homebrew-formula.sh - Helper script to update Homebrew formula with new release 4 + # 5 + # Usage: ./scripts/update-homebrew-formula.sh <version> 6 + # 7 + # Example: ./scripts/update-homebrew-formula.sh v0.0.2 8 + # 9 + # This script: 10 + # 1. Downloads the source tarball from GitHub 11 + # 2. Calculates SHA256 checksum 12 + # 3. Generates updated formula snippet 13 + # 14 + 15 + set -euo pipefail 16 + 17 + # Colors for output 18 + RED='\033[0;31m' 19 + GREEN='\033[0;32m' 20 + YELLOW='\033[1;33m' 21 + NC='\033[0m' # No Color 22 + 23 + # Check arguments 24 + if [ $# -ne 1 ]; then 25 + echo -e "${RED}Error: Missing required argument${NC}" 26 + echo "Usage: $0 <version>" 27 + echo "" 28 + echo "Example: $0 v0.0.2" 29 + echo " $0 0.0.2 (v prefix is optional)" 30 + exit 1 31 + fi 32 + 33 + VERSION="$1" 34 + 35 + # Add 'v' prefix if not present 36 + if [[ ! "$VERSION" =~ ^v ]]; then 37 + VERSION="v${VERSION}" 38 + fi 39 + 40 + echo -e "${GREEN}Updating Homebrew formula for version ${VERSION}${NC}" 41 + echo "" 42 + 43 + # GitHub repository details 44 + GITHUB_REPO="atcr-io/atcr" 45 + TARBALL_URL="https://github.com/${GITHUB_REPO}/archive/refs/tags/${VERSION}.tar.gz" 46 + 47 + # Create temporary directory 48 + TEMP_DIR=$(mktemp -d) 49 + trap 'rm -rf "$TEMP_DIR"' EXIT 50 + 51 + TARBALL_FILE="${TEMP_DIR}/${VERSION}.tar.gz" 52 + 53 + echo -e "${YELLOW}Downloading source tarball...${NC}" 54 + echo "URL: ${TARBALL_URL}" 55 + 56 + if curl -sSfL -o "$TARBALL_FILE" "$TARBALL_URL"; then 57 + # Calculate SHA256 58 + if command -v sha256sum &> /dev/null; then 59 + CHECKSUM=$(sha256sum "$TARBALL_FILE" | awk '{print $1}') 60 + elif command -v shasum &> /dev/null; then 61 + CHECKSUM=$(shasum -a 256 "$TARBALL_FILE" | awk '{print $1}') 62 + else 63 + echo -e "${RED}Error: sha256sum or shasum command not found${NC}" 64 + exit 1 65 + fi 66 + 67 + echo -e "${GREEN}✓ Downloaded successfully${NC}" 68 + echo "SHA256: $CHECKSUM" 69 + else 70 + echo -e "${RED}✗ Failed to download source tarball${NC}" 71 + echo "" 72 + echo "Make sure the tag ${VERSION} exists on GitHub:" 73 + echo " https://github.com/${GITHUB_REPO}/releases/tag/${VERSION}" 74 + echo "" 75 + echo "If you haven't pushed the tag yet, run:" 76 + echo " git tag ${VERSION}" 77 + echo " git push origin ${VERSION}" 78 + exit 1 79 + fi 80 + 81 + echo "" 82 + echo "======================================================================" 83 + echo "Copy the following to Formula/docker-credential-atcr.rb:" 84 + echo "======================================================================" 85 + echo "" 86 + 87 + cat << EOF 88 + url "https://github.com/${GITHUB_REPO}/archive/refs/tags/${VERSION}.tar.gz" 89 + sha256 "${CHECKSUM}" 90 + license "MIT" 91 + head "https://github.com/${GITHUB_REPO}.git", branch: "main" 92 + EOF 93 + 94 + echo "" 95 + echo "======================================================================" 96 + echo "" 97 + echo -e "${YELLOW}Next steps:${NC}" 98 + echo "1. Update Formula/docker-credential-atcr.rb with the url and sha256 above" 99 + echo "2. Test the formula locally:" 100 + echo " brew install --build-from-source Formula/docker-credential-atcr.rb" 101 + echo " docker-credential-atcr version" 102 + echo "3. Commit and push to your atcr-io/homebrew-tap repository:" 103 + echo " cd /path/to/homebrew-tap" 104 + echo " cp Formula/docker-credential-atcr.rb ." 105 + echo " git add docker-credential-atcr.rb" 106 + echo " git commit -m \"Update docker-credential-atcr to ${VERSION}\"" 107 + echo " git push" 108 + echo "4. Users can upgrade with:" 109 + echo " brew update" 110 + echo " brew upgrade docker-credential-atcr"