#!/usr/bin/env bash # # Upload a repo/ tree -- signed APKs plus the signed index -- to an # S3-compatible bucket. # # AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=... \ # bash publish.sh /repo [] # # Bucket, endpoint and prefix are all arguments, never baked in here: this # repo does not know, and per fdroid-repo-ci#1 must never come to know, which # bucket or host any consumer publishes to. Credentials come from the # standard AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY/AWS_SESSION_TOKEN # environment variables that `aws` itself reads -- nothing here parses or # forwards them as arguments. # # Region is required by the `aws` CLI even against a non-AWS S3-compatible # backend that ignores it; set AWS_DEFAULT_REGION if the endpoint cares, # otherwise the placeholder below is never actually consulted. # # Uses `aws s3 sync`, not `cp --recursive`: re-publishing re-uploads only # what changed. Does **not** pass `--delete` by default -- an F-Droid repo # normally keeps every APK it has ever served (older index entries can still # point at them), so silently pruning the remote on every publish is the # wrong default. Pass `--delete` as an extra argument if a caller genuinely # wants the remote pruned to match local. # # `fdroid update` needs no network; this is the one script in this repo that # does (fdroid-repo-ci#1), and is accordingly the one script whose happy path # the test suite cannot exercise against a real bucket. `--dry-run` prints # the exact command this script would run -- including the `with-nixpkgs.sh` # pin -- and exits without touching the network, which is what the test # suite asserts against. (A PATH-stubbed `aws` cannot do this job: `nix # shell` puts the packages it was asked for at the *front* of PATH, ahead of # anything already there, so a stub earlier on the caller's PATH would simply # be shadowed by the real `aws` from awscli2.) Separately, the test suite # also runs this for real against a closed local port, to confirm the # constructed command is well-formed and genuinely attempts a network call # rather than failing on argument parsing. # # Pins awscli2 via with-nixpkgs.sh/nixpkgs-pin, next to this script. set -euo pipefail here=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) if [ "$#" -lt 3 ]; then cat >&2 <<'USAGE' usage: publish.sh [--dry-run] [] [extra aws s3 sync args...] Credentials: AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY (and optionally AWS_SESSION_TOKEN) must already be exported -- never passed as arguments. USAGE exit 2 fi dry_run=false if [ "$1" = "--dry-run" ]; then dry_run=true shift fi local_dir=$1 bucket=$2 endpoint=$3 shift 3 prefix="" if [ "$#" -gt 0 ] && [[ $1 != -* ]]; then prefix=$1 shift fi extra_args=("$@") [ -d "$local_dir" ] || { echo "publish.sh: no such directory: $local_dir" >&2; exit 2; } : "${AWS_ACCESS_KEY_ID:?publish.sh: AWS_ACCESS_KEY_ID is not set}" : "${AWS_SECRET_ACCESS_KEY:?publish.sh: AWS_SECRET_ACCESS_KEY is not set}" dest="s3://$bucket" if [ -n "$prefix" ]; then dest="$dest/${prefix#/}" fi cmd=(bash "$here/with-nixpkgs.sh" awscli2 aws s3 sync "$local_dir" "$dest" --endpoint-url "$endpoint" --region "${AWS_DEFAULT_REGION:-us-east-1}" "${extra_args[@]}") if [ "$dry_run" = true ]; then printf '%q ' "${cmd[@]}" printf '\n' exit 0 fi echo "publish.sh: syncing $local_dir -> $dest (endpoint $endpoint)" exec "${cmd[@]}"