Compare commits
2 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8fefd54d90 | ||
|
|
1a13b77295 |
10
.bazelignore
|
|
@ -1,10 +0,0 @@
|
||||||
.build
|
|
||||||
.derived-data
|
|
||||||
.git
|
|
||||||
.nscloud-cache
|
|
||||||
Apple/build
|
|
||||||
ci-artifacts
|
|
||||||
dist
|
|
||||||
publish
|
|
||||||
release
|
|
||||||
target
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
9.1.0
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
[alias] # command aliases
|
|
||||||
rr = "run --release"
|
|
||||||
bb = "build --release"
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
# Xcode
|
|
||||||
Apple/
|
|
||||||
|
|
||||||
# Rust
|
|
||||||
target/
|
|
||||||
|
|
@ -1,327 +0,0 @@
|
||||||
name: Decrypt Release Secrets
|
|
||||||
description: Decrypts age-sealed Burrow release secrets and exports CI paths/env.
|
|
||||||
inputs:
|
|
||||||
root:
|
|
||||||
description: Repository root
|
|
||||||
required: false
|
|
||||||
default: .
|
|
||||||
runs:
|
|
||||||
using: composite
|
|
||||||
steps:
|
|
||||||
- shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
ROOT_INPUT='${{ inputs.root }}'
|
|
||||||
ROOT="$(cd "$ROOT_INPUT" && pwd)"
|
|
||||||
|
|
||||||
resolve_nix_bin() {
|
|
||||||
local candidate
|
|
||||||
for candidate in \
|
|
||||||
"${NIX_BIN:-}" \
|
|
||||||
"$(command -v nix 2>/dev/null || true)" \
|
|
||||||
/nix/var/nix/profiles/default/bin/nix \
|
|
||||||
"${HOME:-}/.nix-profile/bin/nix" \
|
|
||||||
"${HOME:-}/.local/state/nix/profile/bin/nix" \
|
|
||||||
/Users/runner/.nix-profile/bin/nix \
|
|
||||||
/Users/runner/.local/state/nix/profile/bin/nix \
|
|
||||||
/home/runner/.nix-profile/bin/nix \
|
|
||||||
/home/runner/.local/state/nix/profile/bin/nix \
|
|
||||||
; do
|
|
||||||
if [[ -n "$candidate" && -x "$candidate" ]]; then
|
|
||||||
printf '%s\n' "$candidate"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve_decrypt_tool() {
|
|
||||||
local candidate
|
|
||||||
for candidate in \
|
|
||||||
"${AGE_BIN:-}" \
|
|
||||||
"$(command -v age 2>/dev/null || true)" \
|
|
||||||
/opt/homebrew/bin/age \
|
|
||||||
/usr/local/bin/age \
|
|
||||||
/usr/bin/age \
|
|
||||||
/run/current-system/sw/bin/age \
|
|
||||||
/etc/profiles/per-user/runner/bin/age \
|
|
||||||
"${HOME:-}/.nix-profile/bin/age" \
|
|
||||||
"${HOME:-}/.local/state/nix/profile/bin/age" \
|
|
||||||
/Users/runner/.nix-profile/bin/age \
|
|
||||||
/Users/runner/.local/state/nix/profile/bin/age \
|
|
||||||
/home/runner/.nix-profile/bin/age \
|
|
||||||
/home/runner/.local/state/nix/profile/bin/age \
|
|
||||||
; do
|
|
||||||
if [[ -n "$candidate" && -x "$candidate" ]]; then
|
|
||||||
printf 'age:%s\n' "$candidate"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
for candidate in \
|
|
||||||
"${AGENIX_BIN:-}" \
|
|
||||||
"$(command -v agenix 2>/dev/null || true)" \
|
|
||||||
; do
|
|
||||||
if [[ -n "$candidate" && -x "$candidate" ]]; then
|
|
||||||
printf 'agenix:%s\n' "$candidate"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
local nix_bin
|
|
||||||
nix_bin="$(resolve_nix_bin || true)"
|
|
||||||
if [[ -n "$nix_bin" ]]; then
|
|
||||||
local built
|
|
||||||
built="$("$nix_bin" --extra-experimental-features 'nix-command flakes' build --no-link "$ROOT#age" --print-out-paths 2>/dev/null | tail -n 1 || true)"
|
|
||||||
if [[ -n "$built" && -x "$built/bin/age" ]]; then
|
|
||||||
printf 'age:%s\n' "$built/bin/age"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
built="$("$nix_bin" --extra-experimental-features 'nix-command flakes' build --no-link "$ROOT#agenix" --print-out-paths 2>/dev/null | tail -n 1 || true)"
|
|
||||||
if [[ -n "$built" && -x "$built/bin/agenix" ]]; then
|
|
||||||
printf 'agenix:%s\n' "$built/bin/agenix"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
echo "::error ::age or agenix is required to decrypt release secrets but neither is available." >&2
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
decrypt_tool="$(resolve_decrypt_tool)"
|
|
||||||
decrypt_kind="${decrypt_tool%%:*}"
|
|
||||||
decrypt_bin="${decrypt_tool#*:}"
|
|
||||||
KEY="${AGE_IDENTITY_PATH:-}"
|
|
||||||
if [[ -z "$KEY" || ! -s "$KEY" ]]; then
|
|
||||||
echo "::error ::Missing age identity. Run Scripts/resolve-age-identity.sh before this action." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
decrypt_age_file() {
|
|
||||||
local file_path="$1"
|
|
||||||
if [[ "$decrypt_kind" == "agenix" ]]; then
|
|
||||||
local agenix_path="$file_path"
|
|
||||||
if [[ "$file_path" == "$ROOT/"* ]]; then
|
|
||||||
agenix_path="${file_path#"$ROOT"/}"
|
|
||||||
fi
|
|
||||||
(cd "$ROOT" && "$decrypt_bin" --identity "$KEY" --decrypt "$agenix_path")
|
|
||||||
else
|
|
||||||
"$decrypt_bin" --decrypt -i "$KEY" "$file_path"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
write_env() {
|
|
||||||
local name="$1"
|
|
||||||
local value="$2"
|
|
||||||
echo "${name}=${value}" >> "$GITHUB_ENV"
|
|
||||||
}
|
|
||||||
|
|
||||||
mask_multiline() {
|
|
||||||
local value="$1"
|
|
||||||
echo "::add-mask::${value}"
|
|
||||||
while IFS= read -r line; do
|
|
||||||
[[ -n "$line" ]] || continue
|
|
||||||
echo "::add-mask::${line}"
|
|
||||||
done <<<"$value"
|
|
||||||
}
|
|
||||||
|
|
||||||
decrypt_env_optional() {
|
|
||||||
local name="$1"
|
|
||||||
local file="$2"
|
|
||||||
if [[ ! -f "$file" ]]; then
|
|
||||||
echo "::notice ::Skipping optional release secret ${file}"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
local value
|
|
||||||
value="$(decrypt_age_file "$file")"
|
|
||||||
mask_multiline "$value"
|
|
||||||
{
|
|
||||||
echo "${name}<<EOF"
|
|
||||||
printf '%s\n' "$value"
|
|
||||||
echo "EOF"
|
|
||||||
} >> "$GITHUB_ENV"
|
|
||||||
}
|
|
||||||
|
|
||||||
decrypt_file_optional() {
|
|
||||||
local name="$1"
|
|
||||||
local file="$2"
|
|
||||||
local suffix="$3"
|
|
||||||
if [[ ! -f "$file" ]]; then
|
|
||||||
echo "::notice ::Skipping optional release secret ${file}"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
local temp_dir="${RUNNER_TEMP:-/tmp}"
|
|
||||||
local temp_file
|
|
||||||
temp_file="$(mktemp "${temp_dir}/${name}.XXXXXX")"
|
|
||||||
if [[ -n "$suffix" ]]; then
|
|
||||||
local with_suffix="${temp_file}.${suffix}"
|
|
||||||
mv "$temp_file" "$with_suffix"
|
|
||||||
temp_file="$with_suffix"
|
|
||||||
fi
|
|
||||||
decrypt_age_file "$file" > "$temp_file"
|
|
||||||
chmod 600 "$temp_file"
|
|
||||||
write_env "$name" "$temp_file"
|
|
||||||
}
|
|
||||||
|
|
||||||
decrypt_dotenv_optional() {
|
|
||||||
local file="$1"
|
|
||||||
if [[ ! -f "$file" ]]; then
|
|
||||||
echo "::notice ::Skipping optional release secret ${file}"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
local temp_file
|
|
||||||
temp_file="$(mktemp "${RUNNER_TEMP:-/tmp}/burrow-release-dotenv.XXXXXX")"
|
|
||||||
decrypt_age_file "$file" > "$temp_file"
|
|
||||||
# shellcheck disable=SC1090
|
|
||||||
set -a
|
|
||||||
source "$temp_file"
|
|
||||||
set +a
|
|
||||||
rm -f "$temp_file"
|
|
||||||
|
|
||||||
if [[ -z "${MINIO_ROOT_USER:-}" || -z "${MINIO_ROOT_PASSWORD:-}" ]]; then
|
|
||||||
echo "::error ::${file} must define MINIO_ROOT_USER and MINIO_ROOT_PASSWORD." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
echo "::add-mask::${MINIO_ROOT_USER}"
|
|
||||||
echo "::add-mask::${MINIO_ROOT_PASSWORD}"
|
|
||||||
{
|
|
||||||
echo "AWS_ACCESS_KEY_ID=${MINIO_ROOT_USER}"
|
|
||||||
echo "AWS_SECRET_ACCESS_KEY=${MINIO_ROOT_PASSWORD}"
|
|
||||||
echo "AWS_DEFAULT_REGION=${BLOB_REGION:-hel1}"
|
|
||||||
echo "AWS_REGION=${BLOB_REGION:-hel1}"
|
|
||||||
echo "AWS_S3_ENDPOINT_URL=https://${BLOB_ENDPOINT:-hel1.your-objectstorage.com}"
|
|
||||||
} >> "$GITHUB_ENV"
|
|
||||||
}
|
|
||||||
|
|
||||||
decode_base64_stream() {
|
|
||||||
if command -v base64 >/dev/null 2>&1; then
|
|
||||||
base64 -d 2>/dev/null || base64 -D
|
|
||||||
elif command -v openssl >/dev/null 2>&1; then
|
|
||||||
openssl base64 -d -A
|
|
||||||
else
|
|
||||||
echo "::error ::base64 or openssl is required to decode release secrets." >&2
|
|
||||||
return 127
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
decode_base64_to_file() {
|
|
||||||
local output="$1"
|
|
||||||
decode_base64_stream > "$output"
|
|
||||||
}
|
|
||||||
|
|
||||||
decrypt_appstore_connect() {
|
|
||||||
local file="$ROOT/secrets/apple/appstore-connect.env.age"
|
|
||||||
if [[ ! -f "$file" ]]; then
|
|
||||||
echo "::notice ::Skipping optional release secret ${file}"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
local temp_file key_path key_value
|
|
||||||
temp_file="$(mktemp "${RUNNER_TEMP:-/tmp}/burrow-asc-env.XXXXXX")"
|
|
||||||
decrypt_age_file "$file" > "$temp_file"
|
|
||||||
# shellcheck disable=SC1090
|
|
||||||
set -a
|
|
||||||
source "$temp_file"
|
|
||||||
set +a
|
|
||||||
rm -f "$temp_file"
|
|
||||||
|
|
||||||
if [[ -z "${ASC_API_KEY_ID:-}" || -z "${ASC_API_ISSUER_ID:-}" ]]; then
|
|
||||||
echo "::error ::${file} must define ASC_API_KEY_ID and ASC_API_ISSUER_ID." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
key_path="$(mktemp "${RUNNER_TEMP:-/tmp}/burrow-asc-key.XXXXXX.p8")"
|
|
||||||
if [[ -n "${ASC_API_KEY_BASE64:-}" ]]; then
|
|
||||||
printf '%s' "$ASC_API_KEY_BASE64" | decode_base64_to_file "$key_path"
|
|
||||||
elif [[ -n "${ASC_API_KEY_P8_BASE64:-}" ]]; then
|
|
||||||
printf '%s' "$ASC_API_KEY_P8_BASE64" | decode_base64_to_file "$key_path"
|
|
||||||
elif [[ -n "${APPSTORE_KEY:-}" ]]; then
|
|
||||||
printf '%s\n' "$APPSTORE_KEY" > "$key_path"
|
|
||||||
elif [[ -n "${ASC_API_KEY:-}" ]]; then
|
|
||||||
printf '%s\n' "$ASC_API_KEY" > "$key_path"
|
|
||||||
else
|
|
||||||
echo "::error ::${file} must define ASC_API_KEY_BASE64 or ASC_API_KEY." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
chmod 600 "$key_path"
|
|
||||||
key_value="$(cat "$key_path")"
|
|
||||||
mask_multiline "$key_value"
|
|
||||||
echo "::add-mask::${ASC_API_KEY_ID}"
|
|
||||||
echo "::add-mask::${ASC_API_ISSUER_ID}"
|
|
||||||
write_env ASC_API_KEY_ID "$ASC_API_KEY_ID"
|
|
||||||
write_env ASC_API_ISSUER_ID "$ASC_API_ISSUER_ID"
|
|
||||||
write_env ASC_API_KEY_PATH "$key_path"
|
|
||||||
}
|
|
||||||
|
|
||||||
decrypt_distribution_signing() {
|
|
||||||
local file="$ROOT/secrets/apple/distribution-signing.env.age"
|
|
||||||
if [[ ! -f "$file" ]]; then
|
|
||||||
echo "::notice ::Skipping optional release secret ${file}"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
local temp_file cert_path cert_password cert_base64
|
|
||||||
temp_file="$(mktemp "${RUNNER_TEMP:-/tmp}/burrow-signing-env.XXXXXX")"
|
|
||||||
decrypt_age_file "$file" > "$temp_file"
|
|
||||||
# shellcheck disable=SC1090
|
|
||||||
set -a
|
|
||||||
source "$temp_file"
|
|
||||||
set +a
|
|
||||||
rm -f "$temp_file"
|
|
||||||
|
|
||||||
cert_base64="${APPLE_SIGNING_CERTIFICATE_BASE64:-${APPLE_DISTRIBUTION_CERTIFICATE_BASE64:-}}"
|
|
||||||
cert_password="${APPLE_SIGNING_CERTIFICATE_PASSWORD:-${APPLE_DISTRIBUTION_CERTIFICATE_PASSWORD:-}}"
|
|
||||||
if [[ -z "$cert_password" && -n "${APPLE_SIGNING_CERTIFICATE_PASSWORD_BASE64:-}" ]]; then
|
|
||||||
cert_password="$(printf '%s' "$APPLE_SIGNING_CERTIFICATE_PASSWORD_BASE64" | decode_base64_stream)"
|
|
||||||
fi
|
|
||||||
if [[ -z "$cert_base64" || -z "$cert_password" ]]; then
|
|
||||||
echo "::error ::${file} must define APPLE_SIGNING_CERTIFICATE_BASE64 and APPLE_SIGNING_CERTIFICATE_PASSWORD." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
cert_path="$(mktemp "${RUNNER_TEMP:-/tmp}/burrow-apple-signing.XXXXXX.p12")"
|
|
||||||
printf '%s' "$cert_base64" | decode_base64_to_file "$cert_path"
|
|
||||||
chmod 600 "$cert_path"
|
|
||||||
echo "::add-mask::${cert_password}"
|
|
||||||
write_env APPLE_SIGNING_CERTIFICATE_PATH "$cert_path"
|
|
||||||
write_env APPLE_SIGNING_CERTIFICATE_PASSWORD "$cert_password"
|
|
||||||
write_env APPLE_KEYCHAIN_PASSWORD "$cert_password"
|
|
||||||
}
|
|
||||||
|
|
||||||
decrypt_sparkle() {
|
|
||||||
local file="$ROOT/secrets/apple/sparkle.env.age"
|
|
||||||
if [[ ! -f "$file" ]]; then
|
|
||||||
echo "::notice ::Skipping optional release secret ${file}"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
local temp_file key_path key_base64 key_value
|
|
||||||
temp_file="$(mktemp "${RUNNER_TEMP:-/tmp}/burrow-sparkle-env.XXXXXX")"
|
|
||||||
decrypt_age_file "$file" > "$temp_file"
|
|
||||||
# shellcheck disable=SC1090
|
|
||||||
set -a
|
|
||||||
source "$temp_file"
|
|
||||||
set +a
|
|
||||||
rm -f "$temp_file"
|
|
||||||
|
|
||||||
key_base64="${SPARKLE_EDDSA_KEY_BASE64:-${SPARKLE_PRIVATE_KEY_BASE64:-}}"
|
|
||||||
key_path="$(mktemp "${RUNNER_TEMP:-/tmp}/burrow-sparkle-eddsa.XXXXXX.key")"
|
|
||||||
if [[ -n "$key_base64" ]]; then
|
|
||||||
printf '%s' "$key_base64" | decode_base64_to_file "$key_path"
|
|
||||||
elif [[ -n "${SPARKLE_EDDSA_KEY:-}" ]]; then
|
|
||||||
printf '%s\n' "$SPARKLE_EDDSA_KEY" > "$key_path"
|
|
||||||
elif [[ -n "${SPARKLE_PRIVATE_KEY:-}" ]]; then
|
|
||||||
printf '%s\n' "$SPARKLE_PRIVATE_KEY" > "$key_path"
|
|
||||||
else
|
|
||||||
echo "::error ::${file} must define SPARKLE_EDDSA_KEY_BASE64 or SPARKLE_EDDSA_KEY." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
chmod 600 "$key_path"
|
|
||||||
key_value="$(cat "$key_path")"
|
|
||||||
mask_multiline "$key_value"
|
|
||||||
write_env SPARKLE_EDDSA_KEY_PATH "$key_path"
|
|
||||||
}
|
|
||||||
|
|
||||||
decrypt_appstore_connect
|
|
||||||
decrypt_distribution_signing
|
|
||||||
decrypt_sparkle
|
|
||||||
|
|
||||||
decrypt_dotenv_optional "$ROOT/secrets/hetzner/object-storage.age"
|
|
||||||
|
|
@ -1,98 +0,0 @@
|
||||||
name: "Apple: Developer ID KMS CSR"
|
|
||||||
run-name: "Apple: Developer ID KMS CSR (${{ github.event.inputs.kms_key || 'apple-developer-id-application' }})"
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
kms_key:
|
|
||||||
description: Google KMS key name in the Burrow identity key ring
|
|
||||||
required: false
|
|
||||||
default: apple-developer-id-application
|
|
||||||
kms_version:
|
|
||||||
description: Google KMS key version
|
|
||||||
required: false
|
|
||||||
default: "1"
|
|
||||||
common_name:
|
|
||||||
description: CSR common name
|
|
||||||
required: false
|
|
||||||
default: Burrow Developer ID Application
|
|
||||||
email_address:
|
|
||||||
description: CSR email address
|
|
||||||
required: false
|
|
||||||
default: release@burrow.net
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: apple-developer-id-kms-csr-${{ github.ref }}
|
|
||||||
cancel-in-progress: false
|
|
||||||
|
|
||||||
env:
|
|
||||||
BURROW_GOOGLE_PROJECT_ID: ${{ vars.GOOGLE_PROJECT_ID || 'project-88c23ce9-918a-470a-b33' }}
|
|
||||||
GOOGLE_CLOUD_PROJECT: ${{ vars.GOOGLE_PROJECT_ID || 'project-88c23ce9-918a-470a-b33' }}
|
|
||||||
BURROW_GOOGLE_PROJECT_NUMBER: ${{ vars.GOOGLE_PROJECT_NUMBER || '416198671487' }}
|
|
||||||
BURROW_GOOGLE_WIF_POOL_ID: ${{ vars.BURROW_GOOGLE_WIF_POOL_ID || 'burrow-authentik' }}
|
|
||||||
BURROW_GOOGLE_WIF_PROVIDER_ID: ${{ vars.BURROW_GOOGLE_WIF_PROVIDER_ID || 'forgejo-runners' }}
|
|
||||||
BURROW_GOOGLE_WIF_SERVICE_ACCOUNT: ${{ vars.BURROW_GOOGLE_WIF_SERVICE_ACCOUNT || 'burrow-forgejo-runner@project-88c23ce9-918a-470a-b33.iam.gserviceaccount.com' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_ISSUER: ${{ vars.BURROW_AUTHENTIK_WIF_ISSUER || 'https://auth.burrow.net/application/o/google-cloud/' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_AUDIENCE: ${{ vars.BURROW_AUTHENTIK_WIF_AUDIENCE || 'google-wif.burrow.net' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_CLIENT_ID: ${{ vars.BURROW_AUTHENTIK_WIF_CLIENT_ID || 'google-wif.burrow.net' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_CLIENT_SECRET: ${{ secrets.BURROW_AUTHENTIK_WIF_CLIENT_SECRET }}
|
|
||||||
BURROW_KMS_LOCATION: global
|
|
||||||
BURROW_KMS_KEYRING: burrow-identity
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
csr:
|
|
||||||
name: Generate CSR
|
|
||||||
runs-on: [self-hosted, linux, x86_64, burrow-forge]
|
|
||||||
timeout-minutes: 20
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
with:
|
|
||||||
token: ${{ github.token }}
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Ensure Nix
|
|
||||||
shell: bash
|
|
||||||
run: bash Scripts/ci/ensure-nix.sh
|
|
||||||
|
|
||||||
- name: Authenticate Google WIF
|
|
||||||
shell: bash
|
|
||||||
run: nix develop .#ci -c Scripts/ci/google-wif-auth.sh
|
|
||||||
|
|
||||||
- name: Generate KMS-backed CSR
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
BURROW_APPLE_DEVELOPER_ID_KMS_KEY: ${{ github.event.inputs.kms_key || 'apple-developer-id-application' }}
|
|
||||||
BURROW_KMS_VERSION: ${{ github.event.inputs.kms_version || '1' }}
|
|
||||||
BURROW_APPLE_DEVELOPER_ID_CSR_COMMON_NAME: ${{ github.event.inputs.common_name || 'Burrow Developer ID Application' }}
|
|
||||||
BURROW_APPLE_DEVELOPER_ID_CSR_EMAIL: ${{ github.event.inputs.email_address || 'release@burrow.net' }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
mkdir -p dist/apple-developer-id
|
|
||||||
nix develop .#ci -c Scripts/apple/google-kms-csr.py \
|
|
||||||
--output dist/apple-developer-id/developer-id-application.certSigningRequest \
|
|
||||||
--public-key-output dist/apple-developer-id/google-kms-public-key.pem
|
|
||||||
if command -v openssl >/dev/null 2>&1; then
|
|
||||||
openssl req -in dist/apple-developer-id/developer-id-application.certSigningRequest -noout -verify
|
|
||||||
fi
|
|
||||||
cat > dist/apple-developer-id/README.txt <<'EOF'
|
|
||||||
This CSR is backed by a non-exportable Google Cloud KMS key in the Burrow
|
|
||||||
identity key ring. Apple currently documents Developer ID certificate creation
|
|
||||||
through the Developer website or Xcode, not App Store Connect API creation.
|
|
||||||
|
|
||||||
Upload developer-id-application.certSigningRequest in:
|
|
||||||
Certificates, Identifiers & Profiles -> Certificates -> + -> Developer ID ->
|
|
||||||
Developer ID Application.
|
|
||||||
|
|
||||||
Keep the returned .cer file with release artifacts. The private key remains in
|
|
||||||
Google Cloud KMS and is never exported as a p12.
|
|
||||||
EOF
|
|
||||||
|
|
||||||
- name: Upload CSR Artifact
|
|
||||||
uses: https://code.forgejo.org/actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: burrow-developer-id-kms-csr
|
|
||||||
path: dist/apple-developer-id
|
|
||||||
|
|
@ -1,530 +0,0 @@
|
||||||
name: "Apple: Distribute Testers"
|
|
||||||
run-name: "Apple: Distribute Testers (${{ github.ref_name }})"
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
build_number_override:
|
|
||||||
description: Optional explicit build number
|
|
||||||
required: false
|
|
||||||
default: ""
|
|
||||||
upload_app_store:
|
|
||||||
description: Upload iOS artifact to App Store Connect and TestFlight
|
|
||||||
required: false
|
|
||||||
default: "true"
|
|
||||||
upload_sparkle:
|
|
||||||
description: Publish Sparkle appcast and macOS artifact
|
|
||||||
required: false
|
|
||||||
default: "true"
|
|
||||||
sparkle_channel:
|
|
||||||
description: Sparkle channel, defaults to build-<number>
|
|
||||||
required: false
|
|
||||||
default: ""
|
|
||||||
sparkle_point_main:
|
|
||||||
description: Update Sparkle main channel pointers
|
|
||||||
required: false
|
|
||||||
default: "true"
|
|
||||||
testflight_distribute_external:
|
|
||||||
description: Distribute to external TestFlight groups
|
|
||||||
required: false
|
|
||||||
default: "false"
|
|
||||||
testflight_groups:
|
|
||||||
description: Optional comma-separated TestFlight groups
|
|
||||||
required: false
|
|
||||||
default: ""
|
|
||||||
ios_uses_non_exempt_encryption:
|
|
||||||
description: Set true only when the iOS build uses non-exempt encryption
|
|
||||||
required: false
|
|
||||||
default: "false"
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
actions: write
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: burrow-apple-distribute-testers-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
env:
|
|
||||||
BURROW_RELEASE_GCS_BUCKET: ${{ vars.BURROW_RELEASE_GCS_BUCKET || 'burrow-net-releases' }}
|
|
||||||
BURROW_RELEASE_GCS_BACKUP: ${{ vars.BURROW_RELEASE_GCS_BACKUP || 'true' }}
|
|
||||||
BURROW_RELEASE_GARAGE_BUCKET: ${{ vars.BURROW_RELEASE_GARAGE_BUCKET || 'burrow-releases' }}
|
|
||||||
BURROW_RELEASE_REQUIRE_GARAGE: ${{ vars.BURROW_RELEASE_REQUIRE_GARAGE || 'true' }}
|
|
||||||
BURROW_GARAGE_ENDPOINT: ${{ vars.BURROW_GARAGE_ENDPOINT || 'https://objects.burrow.net' }}
|
|
||||||
BURROW_GARAGE_REGION: ${{ vars.BURROW_GARAGE_REGION || 'garage' }}
|
|
||||||
AWS_ACCESS_KEY_ID: ${{ secrets.BURROW_GARAGE_ACCESS_KEY_ID }}
|
|
||||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.BURROW_GARAGE_SECRET_ACCESS_KEY }}
|
|
||||||
BURROW_GOOGLE_PROJECT_ID: ${{ vars.GOOGLE_PROJECT_ID || 'project-88c23ce9-918a-470a-b33' }}
|
|
||||||
GOOGLE_CLOUD_PROJECT: ${{ vars.GOOGLE_PROJECT_ID || 'project-88c23ce9-918a-470a-b33' }}
|
|
||||||
BURROW_GOOGLE_PROJECT_NUMBER: ${{ vars.GOOGLE_PROJECT_NUMBER || '416198671487' }}
|
|
||||||
BURROW_GOOGLE_WIF_POOL_ID: ${{ vars.BURROW_GOOGLE_WIF_POOL_ID || 'burrow-authentik' }}
|
|
||||||
BURROW_GOOGLE_WIF_PROVIDER_ID: ${{ vars.BURROW_GOOGLE_WIF_PROVIDER_ID || 'forgejo-runners' }}
|
|
||||||
BURROW_GOOGLE_WIF_SERVICE_ACCOUNT: ${{ vars.BURROW_GOOGLE_WIF_SERVICE_ACCOUNT || 'burrow-forgejo-runner@project-88c23ce9-918a-470a-b33.iam.gserviceaccount.com' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_ISSUER: ${{ vars.BURROW_AUTHENTIK_WIF_ISSUER || 'https://auth.burrow.net/application/o/google-cloud/' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_AUDIENCE: ${{ vars.BURROW_AUTHENTIK_WIF_AUDIENCE || 'google-wif.burrow.net' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_CLIENT_ID: ${{ vars.BURROW_AUTHENTIK_WIF_CLIENT_ID || 'google-wif.burrow.net' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_CLIENT_SECRET: ${{ secrets.BURROW_AUTHENTIK_WIF_CLIENT_SECRET }}
|
|
||||||
BURROW_NIX_CACHE_URL: ${{ vars.BURROW_NIX_CACHE_URL || 'https://nix.burrow.net/burrow' }}
|
|
||||||
BURROW_NIX_CACHE_PUBLIC_KEY: ${{ vars.BURROW_NIX_CACHE_PUBLIC_KEY }}
|
|
||||||
BURROW_APPLE_BUNDLE_ID: ${{ vars.BURROW_APPLE_BUNDLE_ID || 'net.burrow.app' }}
|
|
||||||
BURROW_APPLE_NETWORK_EXTENSION_BUNDLE_ID: ${{ vars.BURROW_APPLE_NETWORK_EXTENSION_BUNDLE_ID || 'net.burrow.app.network' }}
|
|
||||||
BURROW_IOS_DISTRIBUTION_CERTIFICATE_ID: ${{ vars.BURROW_IOS_DISTRIBUTION_CERTIFICATE_ID || '3G42677598' }}
|
|
||||||
BURROW_DEVELOPER_ID_CERTIFICATE_ID: ${{ vars.BURROW_DEVELOPER_ID_CERTIFICATE_ID || '9JKN6HXBHC' }}
|
|
||||||
BURROW_APPLE_SIGNING_MODE: google-kms-staged
|
|
||||||
BURROW_NOTARIZE_MACOS: ${{ vars.BURROW_NOTARIZE_MACOS || 'true' }}
|
|
||||||
BURROW_SPARKLE_SIGN_WITH_KMS: ${{ vars.BURROW_SPARKLE_SIGN_WITH_KMS || 'true' }}
|
|
||||||
BURROW_SPARKLE_KMS_KEY: ${{ vars.BURROW_SPARKLE_KMS_KEY || 'sparkle-ed25519' }}
|
|
||||||
BURROW_SPARKLE_KMS_VERSION: ${{ vars.BURROW_SPARKLE_KMS_VERSION || '1' }}
|
|
||||||
BURROW_SPARKLE_FEED_URL: ${{ vars.BURROW_SPARKLE_FEED_URL || 'https://releases.burrow.net/sparkle/appcast.xml' }}
|
|
||||||
BURROW_SPARKLE_PUBLIC_ED_KEY: ${{ vars.BURROW_SPARKLE_PUBLIC_ED_KEY || 'uugZuJeqvvKd91NZ6F1Fv2cQenUbIG/ZW3L9MuaEz30=' }}
|
|
||||||
BURROW_KMS_LOCATION: ${{ vars.BURROW_KMS_LOCATION || 'global' }}
|
|
||||||
BURROW_KMS_KEYRING: ${{ vars.BURROW_KMS_KEYRING || 'burrow-identity' }}
|
|
||||||
TESTFLIGHT_WAIT_PROCESSING_TIMEOUT_SECONDS: ${{ vars.TESTFLIGHT_WAIT_PROCESSING_TIMEOUT_SECONDS || '7200' }}
|
|
||||||
BURROW_VERSION_REQUIRE_REMOTE: "1"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
prepare:
|
|
||||||
name: Prepare Apple Distribution
|
|
||||||
runs-on: namespace-profile-linux-medium-apple-v2
|
|
||||||
outputs:
|
|
||||||
build_number: ${{ steps.plan.outputs.build_number }}
|
|
||||||
sparkle_channel: ${{ steps.plan.outputs.sparkle_channel }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
with:
|
|
||||||
token: ${{ github.token }}
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Fetch Build Tags
|
|
||||||
shell: bash
|
|
||||||
run: git fetch --force --prune origin "+refs/tags/builds/*:refs/tags/builds/*"
|
|
||||||
|
|
||||||
- name: Compute Apple Distribution Plan
|
|
||||||
id: plan
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
BUILD_NUMBER_OVERRIDE: ${{ github.event.inputs.build_number_override || '' }}
|
|
||||||
SPARKLE_CHANNEL_INPUT: ${{ github.event.inputs.sparkle_channel || '' }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
if [[ -n "$BUILD_NUMBER_OVERRIDE" ]]; then
|
|
||||||
build_number="$BUILD_NUMBER_OVERRIDE"
|
|
||||||
else
|
|
||||||
build_number="$(Scripts/version.sh pre-increment)"
|
|
||||||
fi
|
|
||||||
channel="$SPARKLE_CHANNEL_INPUT"
|
|
||||||
if [[ -z "$channel" ]]; then
|
|
||||||
channel="build-${build_number}"
|
|
||||||
fi
|
|
||||||
echo "build_number=${build_number}" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "sparkle_channel=${channel}" >> "$GITHUB_OUTPUT"
|
|
||||||
printf 'build_number=%s\nsparkle_channel=%s\n' "$build_number" "$channel"
|
|
||||||
|
|
||||||
build-ios:
|
|
||||||
name: Build Apple iOS
|
|
||||||
needs: prepare
|
|
||||||
runs-on: namespace-profile-macos-large-apple-v2
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
with:
|
|
||||||
token: ${{ github.token }}
|
|
||||||
fetch-depth: 0
|
|
||||||
submodules: recursive
|
|
||||||
|
|
||||||
- name: Select Apple SDK
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
xcrun --find swiftc
|
|
||||||
xcrun --sdk iphoneos --show-sdk-path
|
|
||||||
xcrun --sdk iphonesimulator --show-sdk-path
|
|
||||||
|
|
||||||
- name: Prepare Rust Apple Targets
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
if ! command -v rustup >/dev/null 2>&1; then
|
|
||||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain stable
|
|
||||||
export PATH="$HOME/.cargo/bin:$PATH"
|
|
||||||
fi
|
|
||||||
rustup target add aarch64-apple-ios aarch64-apple-ios-sim x86_64-apple-ios
|
|
||||||
|
|
||||||
- name: Bootstrap Runner Environment
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
runner_home="${RUNNER_HOME:-}"
|
|
||||||
if [[ -z "$runner_home" ]]; then
|
|
||||||
runner_home="$(python3 -c 'import os,pwd; print(pwd.getpwuid(os.getuid()).pw_dir)' 2>/dev/null || true)"
|
|
||||||
if [[ -z "$runner_home" ]]; then
|
|
||||||
runner_home="$PWD/.home"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
mkdir -p "$runner_home" "$PWD/.tmp"
|
|
||||||
{
|
|
||||||
echo "HOME=$runner_home"
|
|
||||||
echo "XDG_CACHE_HOME=$runner_home/.cache"
|
|
||||||
echo "XDG_CONFIG_HOME=$runner_home/.config"
|
|
||||||
echo "XDG_DATA_HOME=$runner_home/.local/share"
|
|
||||||
echo "TMPDIR=$PWD/.tmp"
|
|
||||||
echo "TMP=$PWD/.tmp"
|
|
||||||
} >> "$GITHUB_ENV"
|
|
||||||
|
|
||||||
- name: Ensure Nix
|
|
||||||
shell: bash
|
|
||||||
run: bash Scripts/ci/ensure-nix.sh
|
|
||||||
|
|
||||||
- name: Namespace Cache
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
bash Scripts/ci/nscloud-cache.sh bazel
|
|
||||||
|
|
||||||
- name: Build Staged iOS Artifact
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
BUILD_NUMBER: ${{ needs.prepare.outputs.build_number }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
bazel_args=()
|
|
||||||
if [[ -n "${BURROW_BAZEL_NSCCACHE_BAZELRC:-}" && -f "${BURROW_BAZEL_NSCCACHE_BAZELRC:-}" ]]; then
|
|
||||||
bazel_args+=("--bazelrc=${BURROW_BAZEL_NSCCACHE_BAZELRC}")
|
|
||||||
fi
|
|
||||||
NIX_BIN="$(bash Scripts/ci/resolve-nix-bin.sh)"
|
|
||||||
ci_path="$("$NIX_BIN" develop .#ci --command bash -lc 'printf "%s" "$PATH"')"
|
|
||||||
ci_protoc="$("$NIX_BIN" develop .#ci --command bash -lc 'command -v protoc')"
|
|
||||||
"$NIX_BIN" develop .#ci --command bazel "${bazel_args[@]}" build \
|
|
||||||
--verbose_failures \
|
|
||||||
--show_timestamps \
|
|
||||||
--experimental_ui_max_stdouterr_bytes=16777216 \
|
|
||||||
--action_env=PATH="$ci_path" \
|
|
||||||
--action_env=PROTOC="$ci_protoc" \
|
|
||||||
--action_env=BUILD_WORKSPACE_DIRECTORY="$PWD" \
|
|
||||||
--action_env=BUILD_NUMBER="$BUILD_NUMBER" \
|
|
||||||
--action_env=BURROW_RELEASE_OUT="$PWD/dist/builds/$BUILD_NUMBER" \
|
|
||||||
--action_env=BURROW_APPLE_SIGNING_MODE="$BURROW_APPLE_SIGNING_MODE" \
|
|
||||||
--action_env=BURROW_APPLE_REQUIRE_SIGNING=true \
|
|
||||||
--action_env=BURROW_APPLE_BUNDLE_ID="$BURROW_APPLE_BUNDLE_ID" \
|
|
||||||
--action_env=BURROW_APPLE_NETWORK_EXTENSION_BUNDLE_ID="$BURROW_APPLE_NETWORK_EXTENSION_BUNDLE_ID" \
|
|
||||||
--action_env=HOME="$HOME" \
|
|
||||||
--action_env=XDG_CACHE_HOME="$XDG_CACHE_HOME" \
|
|
||||||
//bazel/apple:release_ios_stamp
|
|
||||||
|
|
||||||
- name: Upload Staged iOS Artifact
|
|
||||||
uses: https://code.forgejo.org/actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: burrow-apple-ios-${{ needs.prepare.outputs.build_number }}
|
|
||||||
path: |
|
|
||||||
dist/builds/${{ needs.prepare.outputs.build_number }}/apple/Burrow-iOS-${{ needs.prepare.outputs.build_number }}.unsigned.ipa
|
|
||||||
dist/builds/${{ needs.prepare.outputs.build_number }}/apple/Burrow-iOS-${{ needs.prepare.outputs.build_number }}.unsigned.ipa.sha256
|
|
||||||
if-no-files-found: error
|
|
||||||
|
|
||||||
build-macos:
|
|
||||||
name: Build Apple macOS
|
|
||||||
needs: prepare
|
|
||||||
runs-on: namespace-profile-macos-large-apple-v2
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
with:
|
|
||||||
token: ${{ github.token }}
|
|
||||||
fetch-depth: 0
|
|
||||||
submodules: recursive
|
|
||||||
|
|
||||||
- name: Select Apple SDK
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
xcrun --find swiftc
|
|
||||||
xcrun --sdk macosx --show-sdk-path
|
|
||||||
|
|
||||||
- name: Prepare Rust Apple Targets
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
if ! command -v rustup >/dev/null 2>&1; then
|
|
||||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain stable
|
|
||||||
export PATH="$HOME/.cargo/bin:$PATH"
|
|
||||||
fi
|
|
||||||
rustup target add aarch64-apple-darwin x86_64-apple-darwin
|
|
||||||
|
|
||||||
- name: Bootstrap Runner Environment
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
runner_home="${RUNNER_HOME:-}"
|
|
||||||
if [[ -z "$runner_home" ]]; then
|
|
||||||
runner_home="$(python3 -c 'import os,pwd; print(pwd.getpwuid(os.getuid()).pw_dir)' 2>/dev/null || true)"
|
|
||||||
if [[ -z "$runner_home" ]]; then
|
|
||||||
runner_home="$PWD/.home"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
mkdir -p "$runner_home" "$PWD/.tmp"
|
|
||||||
{
|
|
||||||
echo "HOME=$runner_home"
|
|
||||||
echo "XDG_CACHE_HOME=$runner_home/.cache"
|
|
||||||
echo "XDG_CONFIG_HOME=$runner_home/.config"
|
|
||||||
echo "XDG_DATA_HOME=$runner_home/.local/share"
|
|
||||||
echo "TMPDIR=$PWD/.tmp"
|
|
||||||
echo "TMP=$PWD/.tmp"
|
|
||||||
} >> "$GITHUB_ENV"
|
|
||||||
|
|
||||||
- name: Ensure Nix
|
|
||||||
shell: bash
|
|
||||||
run: bash Scripts/ci/ensure-nix.sh
|
|
||||||
|
|
||||||
- name: Namespace Cache
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
bash Scripts/ci/nscloud-cache.sh bazel
|
|
||||||
|
|
||||||
- name: Build Staged macOS Artifact
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
BUILD_NUMBER: ${{ needs.prepare.outputs.build_number }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
bazel_args=()
|
|
||||||
if [[ -n "${BURROW_BAZEL_NSCCACHE_BAZELRC:-}" && -f "${BURROW_BAZEL_NSCCACHE_BAZELRC:-}" ]]; then
|
|
||||||
bazel_args+=("--bazelrc=${BURROW_BAZEL_NSCCACHE_BAZELRC}")
|
|
||||||
fi
|
|
||||||
NIX_BIN="$(bash Scripts/ci/resolve-nix-bin.sh)"
|
|
||||||
ci_path="$("$NIX_BIN" develop .#ci --command bash -lc 'printf "%s" "$PATH"')"
|
|
||||||
ci_protoc="$("$NIX_BIN" develop .#ci --command bash -lc 'command -v protoc')"
|
|
||||||
"$NIX_BIN" develop .#ci --command bazel "${bazel_args[@]}" build \
|
|
||||||
--verbose_failures \
|
|
||||||
--show_timestamps \
|
|
||||||
--experimental_ui_max_stdouterr_bytes=16777216 \
|
|
||||||
--action_env=PATH="$ci_path" \
|
|
||||||
--action_env=PROTOC="$ci_protoc" \
|
|
||||||
--action_env=BUILD_WORKSPACE_DIRECTORY="$PWD" \
|
|
||||||
--action_env=BUILD_NUMBER="$BUILD_NUMBER" \
|
|
||||||
--action_env=BURROW_RELEASE_OUT="$PWD/dist/builds/$BUILD_NUMBER" \
|
|
||||||
--action_env=BURROW_APPLE_SIGNING_MODE="$BURROW_APPLE_SIGNING_MODE" \
|
|
||||||
--action_env=BURROW_APPLE_REQUIRE_SIGNING=true \
|
|
||||||
--action_env=BURROW_APPLE_BUNDLE_ID="$BURROW_APPLE_BUNDLE_ID" \
|
|
||||||
--action_env=BURROW_APPLE_NETWORK_EXTENSION_BUNDLE_ID="$BURROW_APPLE_NETWORK_EXTENSION_BUNDLE_ID" \
|
|
||||||
--action_env=BURROW_SPARKLE_FEED_URL="$BURROW_SPARKLE_FEED_URL" \
|
|
||||||
--action_env=BURROW_SPARKLE_PUBLIC_ED_KEY="$BURROW_SPARKLE_PUBLIC_ED_KEY" \
|
|
||||||
--action_env=HOME="$HOME" \
|
|
||||||
--action_env=XDG_CACHE_HOME="$XDG_CACHE_HOME" \
|
|
||||||
//bazel/apple:release_macos_stamp
|
|
||||||
|
|
||||||
- name: Upload Staged macOS Artifact
|
|
||||||
uses: https://code.forgejo.org/actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: burrow-apple-macos-${{ needs.prepare.outputs.build_number }}
|
|
||||||
path: |
|
|
||||||
dist/builds/${{ needs.prepare.outputs.build_number }}/apple/Burrow-macOS-${{ needs.prepare.outputs.build_number }}.unsigned.zip
|
|
||||||
dist/builds/${{ needs.prepare.outputs.build_number }}/apple/Burrow-macOS-${{ needs.prepare.outputs.build_number }}.unsigned.zip.sha256
|
|
||||||
if-no-files-found: error
|
|
||||||
|
|
||||||
sign-apple:
|
|
||||||
name: Sign Apple Artifacts
|
|
||||||
needs:
|
|
||||||
- prepare
|
|
||||||
- build-ios
|
|
||||||
- build-macos
|
|
||||||
runs-on: namespace-profile-linux-medium-apple-v2
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
with:
|
|
||||||
token: ${{ github.token }}
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Ensure Nix
|
|
||||||
shell: bash
|
|
||||||
run: bash Scripts/ci/ensure-nix.sh
|
|
||||||
|
|
||||||
- name: Configure Age
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
AGE_FORGE_SSH_KEY: ${{ secrets.AGE_FORGE_SSH_KEY }}
|
|
||||||
run: Scripts/resolve-age-identity.sh >> "$GITHUB_ENV"
|
|
||||||
|
|
||||||
- name: Decrypt Release Secrets
|
|
||||||
uses: ./.forgejo/actions/decrypt-release-secrets
|
|
||||||
|
|
||||||
- name: Validate App Store Credentials
|
|
||||||
shell: bash
|
|
||||||
run: Scripts/ci/check-release-config.sh app-store
|
|
||||||
|
|
||||||
- name: Authenticate Google WIF
|
|
||||||
shell: bash
|
|
||||||
run: nix develop .#ci -c Scripts/ci/google-wif-auth.sh
|
|
||||||
|
|
||||||
- name: Download Staged Apple Artifacts
|
|
||||||
uses: https://code.forgejo.org/actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
path: dist/downloaded
|
|
||||||
|
|
||||||
- name: Prepare Staged Apple Directory
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
BUILD_NUMBER: ${{ needs.prepare.outputs.build_number }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
mkdir -p "dist/builds/${BUILD_NUMBER}/apple"
|
|
||||||
find dist/downloaded -type f -name 'Burrow-*.unsigned.*' -exec cp -v {} "dist/builds/${BUILD_NUMBER}/apple/" \;
|
|
||||||
find "dist/builds/${BUILD_NUMBER}/apple" -type f -print | sort
|
|
||||||
|
|
||||||
- name: Sync Apple Provisioning Profiles
|
|
||||||
shell: bash
|
|
||||||
run: nix develop .#ci -c Scripts/ci/sync-apple-provisioning-profiles.sh all
|
|
||||||
|
|
||||||
- name: Sign Apple Artifacts With KMS
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
BUILD_NUMBER: ${{ needs.prepare.outputs.build_number }}
|
|
||||||
SPARKLE_CHANNEL: ${{ needs.prepare.outputs.sparkle_channel }}
|
|
||||||
run: nix develop .#ci -c Scripts/apple/sign-release-artifacts-kms.sh all
|
|
||||||
|
|
||||||
- name: Upload Signed Apple Artifacts To Release Storage
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
BUILD_NUMBER: ${{ needs.prepare.outputs.build_number }}
|
|
||||||
run: nix develop .#ci -c Scripts/ci/upload-release-storage.sh
|
|
||||||
|
|
||||||
- name: Upload Signed Apple Artifacts
|
|
||||||
uses: https://code.forgejo.org/actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: burrow-apple-signed-${{ needs.prepare.outputs.build_number }}
|
|
||||||
path: |
|
|
||||||
dist/builds/${{ needs.prepare.outputs.build_number }}/apple/Burrow-iOS-${{ needs.prepare.outputs.build_number }}.ipa
|
|
||||||
dist/builds/${{ needs.prepare.outputs.build_number }}/apple/Burrow-iOS-${{ needs.prepare.outputs.build_number }}.ipa.sha256
|
|
||||||
dist/builds/${{ needs.prepare.outputs.build_number }}/apple/Burrow-macOS-${{ needs.prepare.outputs.build_number }}.zip
|
|
||||||
dist/builds/${{ needs.prepare.outputs.build_number }}/apple/Burrow-macOS-${{ needs.prepare.outputs.build_number }}.zip.sha256
|
|
||||||
dist/builds/${{ needs.prepare.outputs.build_number }}/sparkle/**
|
|
||||||
if-no-files-found: error
|
|
||||||
|
|
||||||
upload-testflight:
|
|
||||||
name: Upload TestFlight
|
|
||||||
needs:
|
|
||||||
- prepare
|
|
||||||
- sign-apple
|
|
||||||
if: ${{ github.event.inputs.upload_app_store == 'true' }}
|
|
||||||
runs-on: namespace-profile-macos-large-testflight
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
with:
|
|
||||||
token: ${{ github.token }}
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Ensure Nix
|
|
||||||
shell: bash
|
|
||||||
run: bash Scripts/ci/ensure-nix.sh
|
|
||||||
|
|
||||||
- name: Configure Age
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
AGE_FORGE_SSH_KEY: ${{ secrets.AGE_FORGE_SSH_KEY }}
|
|
||||||
run: Scripts/resolve-age-identity.sh >> "$GITHUB_ENV"
|
|
||||||
|
|
||||||
- name: Decrypt Release Secrets
|
|
||||||
uses: ./.forgejo/actions/decrypt-release-secrets
|
|
||||||
|
|
||||||
- name: Download Signed Apple Artifacts
|
|
||||||
uses: https://code.forgejo.org/actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: burrow-apple-signed-${{ needs.prepare.outputs.build_number }}
|
|
||||||
path: publish
|
|
||||||
|
|
||||||
- name: Upload iOS IPA To App Store Connect
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
BUILD_NUMBER: ${{ needs.prepare.outputs.build_number }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
Scripts/ci/check-release-config.sh app-store
|
|
||||||
key_dir="${RUNNER_TEMP:-/tmp}/burrow-asc"
|
|
||||||
altool_key_dir="${HOME}/.appstoreconnect/private_keys"
|
|
||||||
mkdir -p "$key_dir" "$altool_key_dir"
|
|
||||||
key_path="$key_dir/AuthKey_${ASC_API_KEY_ID}.p8"
|
|
||||||
if [[ -n "${ASC_API_KEY_PATH:-}" && -f "${ASC_API_KEY_PATH:-}" ]]; then
|
|
||||||
cp "$ASC_API_KEY_PATH" "$key_path"
|
|
||||||
else
|
|
||||||
printf '%s' "$ASC_API_KEY_BASE64" | base64 --decode > "$key_path"
|
|
||||||
fi
|
|
||||||
cp "$key_path" "$altool_key_dir/AuthKey_${ASC_API_KEY_ID}.p8"
|
|
||||||
chmod 600 "$key_path" "$altool_key_dir/AuthKey_${ASC_API_KEY_ID}.p8"
|
|
||||||
ipa="publish/apple/Burrow-iOS-${BUILD_NUMBER}.ipa"
|
|
||||||
if [[ ! -s "$ipa" ]]; then
|
|
||||||
echo "::error ::No signed iOS IPA found at $ipa" >&2
|
|
||||||
find publish -type f -print | sort
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
upload_log="${RUNNER_TEMP:-/tmp}/burrow-altool-ios-${BUILD_NUMBER}.log"
|
|
||||||
set +e
|
|
||||||
xcrun altool --upload-app \
|
|
||||||
--type ios \
|
|
||||||
--file "$ipa" \
|
|
||||||
--apiKey "$ASC_API_KEY_ID" \
|
|
||||||
--apiIssuer "$ASC_API_ISSUER_ID" 2>&1 | tee "$upload_log"
|
|
||||||
altool_status=${PIPESTATUS[0]}
|
|
||||||
set -e
|
|
||||||
if (( altool_status != 0 )) || grep -Eq 'UPLOAD FAILED|Validation failed|ERROR:' "$upload_log"; then
|
|
||||||
echo "::error ::altool reported upload validation failure for $ipa" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Distribute iOS Build To TestFlight
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
BUILD_NUMBER: ${{ needs.prepare.outputs.build_number }}
|
|
||||||
TESTFLIGHT_DISTRIBUTE_EXTERNAL: ${{ github.event.inputs.testflight_distribute_external || 'false' }}
|
|
||||||
TESTFLIGHT_GROUPS: ${{ github.event.inputs.testflight_groups || '' }}
|
|
||||||
IOS_USES_NON_EXEMPT_ENCRYPTION: ${{ github.event.inputs.ios_uses_non_exempt_encryption || 'false' }}
|
|
||||||
run: Scripts/ci/distribute-testflight.sh
|
|
||||||
|
|
||||||
publish-sparkle:
|
|
||||||
name: Publish Sparkle
|
|
||||||
needs:
|
|
||||||
- prepare
|
|
||||||
- sign-apple
|
|
||||||
if: ${{ github.event.inputs.upload_sparkle == 'true' }}
|
|
||||||
runs-on: namespace-profile-linux-medium-apple-v2
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
with:
|
|
||||||
token: ${{ github.token }}
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Ensure Nix
|
|
||||||
shell: bash
|
|
||||||
run: bash Scripts/ci/ensure-nix.sh
|
|
||||||
|
|
||||||
- name: Authenticate Google WIF
|
|
||||||
shell: bash
|
|
||||||
run: nix develop .#ci -c Scripts/ci/google-wif-auth.sh
|
|
||||||
|
|
||||||
- name: Download Signed Apple Artifacts
|
|
||||||
uses: https://code.forgejo.org/actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: burrow-apple-signed-${{ needs.prepare.outputs.build_number }}
|
|
||||||
path: publish
|
|
||||||
|
|
||||||
- name: Publish Sparkle Channel
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
CHANNEL: ${{ needs.prepare.outputs.sparkle_channel }}
|
|
||||||
SPARKLE_POINT_MAIN: ${{ github.event.inputs.sparkle_point_main || 'true' }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
if [[ ! -f "publish/sparkle/${CHANNEL}/appcast.xml" ]]; then
|
|
||||||
echo "::error ::No Sparkle appcast staged for channel ${CHANNEL}" >&2
|
|
||||||
find publish -type f -print | sort
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
nix develop .#ci -c gcloud storage rsync --recursive "publish/sparkle/${CHANNEL}" "gs://${BURROW_RELEASE_GCS_BUCKET}/sparkle/${CHANNEL}"
|
|
||||||
if [[ "$SPARKLE_POINT_MAIN" == "true" ]]; then
|
|
||||||
printf '%s\n' "$CHANNEL" > main-channel.txt
|
|
||||||
nix develop .#ci -c gcloud storage cp main-channel.txt "gs://${BURROW_RELEASE_GCS_BUCKET}/sparkle/main-channel.txt"
|
|
||||||
nix develop .#ci -c gcloud storage cp "publish/sparkle/${CHANNEL}/appcast.xml" "gs://${BURROW_RELEASE_GCS_BUCKET}/sparkle/appcast.xml"
|
|
||||||
nix develop .#ci -c gcloud storage rsync --recursive "publish/sparkle/${CHANNEL}" "gs://${BURROW_RELEASE_GCS_BUCKET}/sparkle/default"
|
|
||||||
fi
|
|
||||||
|
|
@ -1,99 +0,0 @@
|
||||||
name: "Apple: iOS Distribution KMS CSR"
|
|
||||||
run-name: "Apple: iOS Distribution KMS CSR (${{ github.event.inputs.kms_key || 'apple-ios-distribution' }})"
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
kms_key:
|
|
||||||
description: Google KMS key name in the Burrow identity key ring
|
|
||||||
required: false
|
|
||||||
default: apple-ios-distribution
|
|
||||||
kms_version:
|
|
||||||
description: Google KMS key version
|
|
||||||
required: false
|
|
||||||
default: "1"
|
|
||||||
common_name:
|
|
||||||
description: CSR common name
|
|
||||||
required: false
|
|
||||||
default: Burrow iOS Distribution
|
|
||||||
email_address:
|
|
||||||
description: CSR email address
|
|
||||||
required: false
|
|
||||||
default: release@burrow.net
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: apple-ios-distribution-kms-csr-${{ github.ref }}
|
|
||||||
cancel-in-progress: false
|
|
||||||
|
|
||||||
env:
|
|
||||||
BURROW_GOOGLE_PROJECT_ID: ${{ vars.GOOGLE_PROJECT_ID || 'project-88c23ce9-918a-470a-b33' }}
|
|
||||||
GOOGLE_CLOUD_PROJECT: ${{ vars.GOOGLE_PROJECT_ID || 'project-88c23ce9-918a-470a-b33' }}
|
|
||||||
BURROW_GOOGLE_PROJECT_NUMBER: ${{ vars.GOOGLE_PROJECT_NUMBER || '416198671487' }}
|
|
||||||
BURROW_GOOGLE_WIF_POOL_ID: ${{ vars.BURROW_GOOGLE_WIF_POOL_ID || 'burrow-authentik' }}
|
|
||||||
BURROW_GOOGLE_WIF_PROVIDER_ID: ${{ vars.BURROW_GOOGLE_WIF_PROVIDER_ID || 'forgejo-runners' }}
|
|
||||||
BURROW_GOOGLE_WIF_SERVICE_ACCOUNT: ${{ vars.BURROW_GOOGLE_WIF_SERVICE_ACCOUNT || 'burrow-forgejo-runner@project-88c23ce9-918a-470a-b33.iam.gserviceaccount.com' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_ISSUER: ${{ vars.BURROW_AUTHENTIK_WIF_ISSUER || 'https://auth.burrow.net/application/o/google-cloud/' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_AUDIENCE: ${{ vars.BURROW_AUTHENTIK_WIF_AUDIENCE || 'google-wif.burrow.net' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_CLIENT_ID: ${{ vars.BURROW_AUTHENTIK_WIF_CLIENT_ID || 'google-wif.burrow.net' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_CLIENT_SECRET: ${{ secrets.BURROW_AUTHENTIK_WIF_CLIENT_SECRET }}
|
|
||||||
BURROW_KMS_LOCATION: global
|
|
||||||
BURROW_KMS_KEYRING: burrow-identity
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
csr:
|
|
||||||
name: Generate CSR
|
|
||||||
runs-on: [self-hosted, linux, x86_64, burrow-forge]
|
|
||||||
timeout-minutes: 20
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
with:
|
|
||||||
token: ${{ github.token }}
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Ensure Nix
|
|
||||||
shell: bash
|
|
||||||
run: bash Scripts/ci/ensure-nix.sh
|
|
||||||
|
|
||||||
- name: Authenticate Google WIF
|
|
||||||
shell: bash
|
|
||||||
run: nix develop .#ci -c Scripts/ci/google-wif-auth.sh
|
|
||||||
|
|
||||||
- name: Generate KMS-backed CSR
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
mkdir -p dist/apple-ios-distribution
|
|
||||||
nix develop .#ci -c Scripts/apple/google-kms-csr.py \
|
|
||||||
--kms-key "${{ github.event.inputs.kms_key || 'apple-ios-distribution' }}" \
|
|
||||||
--kms-version "${{ github.event.inputs.kms_version || '1' }}" \
|
|
||||||
--common-name "${{ github.event.inputs.common_name || 'Burrow iOS Distribution' }}" \
|
|
||||||
--email-address "${{ github.event.inputs.email_address || 'release@burrow.net' }}" \
|
|
||||||
--output dist/apple-ios-distribution/ios-distribution.certSigningRequest \
|
|
||||||
--public-key-output dist/apple-ios-distribution/google-kms-public-key.pem
|
|
||||||
if command -v openssl >/dev/null 2>&1; then
|
|
||||||
openssl req -in dist/apple-ios-distribution/ios-distribution.certSigningRequest -noout -verify
|
|
||||||
fi
|
|
||||||
cat > dist/apple-ios-distribution/README.txt <<'EOF'
|
|
||||||
This CSR is backed by a non-exportable Google Cloud KMS key in the Burrow
|
|
||||||
identity key ring.
|
|
||||||
|
|
||||||
Create an iOS Distribution certificate explicitly through App Store Connect:
|
|
||||||
|
|
||||||
Scripts/apple/create-asc-certificate.mjs \
|
|
||||||
--certificate-type IOS_DISTRIBUTION \
|
|
||||||
--csr-file ios-distribution.certSigningRequest \
|
|
||||||
--out-dir Apple/Certificates
|
|
||||||
|
|
||||||
Keep the returned .cer file with release artifacts. The private key remains in
|
|
||||||
Google Cloud KMS and is never exported as a p12.
|
|
||||||
EOF
|
|
||||||
|
|
||||||
- name: Upload CSR Artifact
|
|
||||||
uses: https://code.forgejo.org/actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: burrow-ios-distribution-kms-csr
|
|
||||||
path: dist/apple-ios-distribution
|
|
||||||
|
|
@ -1,67 +0,0 @@
|
||||||
name: "Backup: Garage Storage"
|
|
||||||
run-name: "Backup Garage Storage (${{ github.event.inputs.set || 'all' }})"
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: "17 9 * * *"
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
set:
|
|
||||||
description: "Comma-separated backup set: all, releases, packages, nix-cache"
|
|
||||||
required: false
|
|
||||||
default: all
|
|
||||||
delete_unmatched:
|
|
||||||
description: Delete destination objects that are missing from Garage
|
|
||||||
required: false
|
|
||||||
default: "false"
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: backup-garage-storage-${{ github.event.inputs.set || 'all' }}
|
|
||||||
cancel-in-progress: false
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
backup:
|
|
||||||
name: Mirror Garage To GCS
|
|
||||||
runs-on: namespace-profile-linux-medium
|
|
||||||
timeout-minutes: 90
|
|
||||||
env:
|
|
||||||
BURROW_GARAGE_ENDPOINT: ${{ vars.BURROW_GARAGE_ENDPOINT || 'https://objects.burrow.net' }}
|
|
||||||
BURROW_GARAGE_REGION: ${{ vars.BURROW_GARAGE_REGION || 'garage' }}
|
|
||||||
BURROW_GARAGE_BACKUP_SET: ${{ github.event.inputs.set || 'all' }}
|
|
||||||
BURROW_GARAGE_BACKUP_DELETE: ${{ github.event.inputs.delete_unmatched || 'false' }}
|
|
||||||
BURROW_RELEASE_GARAGE_BUCKET: ${{ vars.BURROW_RELEASE_GARAGE_BUCKET || 'burrow-releases' }}
|
|
||||||
BURROW_PACKAGE_GARAGE_BUCKET: ${{ vars.BURROW_PACKAGE_GARAGE_BUCKET || 'burrow-packages' }}
|
|
||||||
BURROW_NIX_CACHE_GARAGE_BUCKET: ${{ vars.BURROW_NIX_CACHE_GARAGE_BUCKET || 'attic' }}
|
|
||||||
BURROW_RELEASE_GCS_BUCKET: ${{ vars.BURROW_RELEASE_GCS_BUCKET || 'burrow-net-releases' }}
|
|
||||||
BURROW_PACKAGE_GCS_BUCKET: ${{ vars.BURROW_PACKAGE_GCS_BUCKET || 'burrow-net-packages' }}
|
|
||||||
BURROW_NIX_CACHE_GCS_BUCKET: ${{ vars.BURROW_NIX_CACHE_GCS_BUCKET || 'burrow-net-nix-cache' }}
|
|
||||||
AWS_ACCESS_KEY_ID: ${{ secrets.BURROW_GARAGE_BACKUP_ACCESS_KEY_ID }}
|
|
||||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.BURROW_GARAGE_BACKUP_SECRET_ACCESS_KEY }}
|
|
||||||
BURROW_GOOGLE_PROJECT_ID: ${{ vars.GOOGLE_PROJECT_ID || 'project-88c23ce9-918a-470a-b33' }}
|
|
||||||
GOOGLE_CLOUD_PROJECT: ${{ vars.GOOGLE_PROJECT_ID || 'project-88c23ce9-918a-470a-b33' }}
|
|
||||||
BURROW_GOOGLE_PROJECT_NUMBER: ${{ vars.GOOGLE_PROJECT_NUMBER || '416198671487' }}
|
|
||||||
BURROW_GOOGLE_WIF_POOL_ID: ${{ vars.BURROW_GOOGLE_WIF_POOL_ID || 'burrow-authentik' }}
|
|
||||||
BURROW_GOOGLE_WIF_PROVIDER_ID: ${{ vars.BURROW_GOOGLE_WIF_PROVIDER_ID || 'forgejo-runners' }}
|
|
||||||
BURROW_GOOGLE_WIF_SERVICE_ACCOUNT: ${{ vars.BURROW_GOOGLE_WIF_SERVICE_ACCOUNT || 'burrow-forgejo-runner@project-88c23ce9-918a-470a-b33.iam.gserviceaccount.com' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_ISSUER: ${{ vars.BURROW_AUTHENTIK_WIF_ISSUER || 'https://auth.burrow.net/application/o/google-cloud/' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_AUDIENCE: ${{ vars.BURROW_AUTHENTIK_WIF_AUDIENCE || 'google-wif.burrow.net' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_CLIENT_ID: ${{ vars.BURROW_AUTHENTIK_WIF_CLIENT_ID || 'google-wif.burrow.net' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_CLIENT_SECRET: ${{ secrets.BURROW_AUTHENTIK_WIF_CLIENT_SECRET }}
|
|
||||||
BURROW_NIX_CACHE_URL: ${{ vars.BURROW_NIX_CACHE_URL || 'https://nix.burrow.net/burrow' }}
|
|
||||||
BURROW_NIX_CACHE_PUBLIC_KEY: ${{ vars.BURROW_NIX_CACHE_PUBLIC_KEY }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Ensure Nix
|
|
||||||
shell: bash
|
|
||||||
run: bash Scripts/ci/ensure-nix.sh
|
|
||||||
|
|
||||||
- name: Mirror Garage Buckets To GCS
|
|
||||||
shell: bash
|
|
||||||
run: nix develop .#ci -c Scripts/ci/backup-garage-to-gcs.sh
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
name: "Build: Android"
|
|
||||||
run-name: "Build: Android (${{ github.ref_name }})"
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths:
|
|
||||||
- ".forgejo/workflows/build-android.yml"
|
|
||||||
- "Android/**"
|
|
||||||
- "BUILD.bazel"
|
|
||||||
- "MODULE.bazel"
|
|
||||||
- "MODULE.bazel.lock"
|
|
||||||
- "bazel/android/**"
|
|
||||||
- "Cargo.lock"
|
|
||||||
- "Cargo.toml"
|
|
||||||
- "crates/burrow-core/**"
|
|
||||||
- "crates/burrow-mobile-ffi/**"
|
|
||||||
- "rust-toolchain.toml"
|
|
||||||
- "Scripts/ci/nscloud-cache.sh"
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- ".forgejo/workflows/build-android.yml"
|
|
||||||
- "Android/**"
|
|
||||||
- "BUILD.bazel"
|
|
||||||
- "MODULE.bazel"
|
|
||||||
- "MODULE.bazel.lock"
|
|
||||||
- "bazel/android/**"
|
|
||||||
- "Cargo.lock"
|
|
||||||
- "Cargo.toml"
|
|
||||||
- "crates/burrow-core/**"
|
|
||||||
- "crates/burrow-mobile-ffi/**"
|
|
||||||
- "rust-toolchain.toml"
|
|
||||||
- "Scripts/ci/nscloud-cache.sh"
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: burrow-build-android-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
env:
|
|
||||||
BURROW_NIX_CACHE_URL: ${{ vars.BURROW_NIX_CACHE_URL || 'https://nix.burrow.net/burrow' }}
|
|
||||||
BURROW_NIX_CACHE_PUBLIC_KEY: ${{ vars.BURROW_NIX_CACHE_PUBLIC_KEY }}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
stub:
|
|
||||||
name: Android Rust Core Stub
|
|
||||||
runs-on: namespace-profile-linux-medium
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
with:
|
|
||||||
token: ${{ github.token }}
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Configure Cache
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
bash Scripts/ci/ensure-nix.sh
|
|
||||||
nix develop .#ci -c Scripts/ci/nscloud-cache.sh bazel
|
|
||||||
|
|
||||||
- name: Build Android Stub Check
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
if [[ -n "${BURROW_BAZEL_NSCCACHE_BAZELRC:-}" ]]; then
|
|
||||||
bazel --bazelrc="$BURROW_BAZEL_NSCCACHE_BAZELRC" build //bazel/android:check_stub_stamp
|
|
||||||
else
|
|
||||||
bazel build //bazel/android:check_stub_stamp
|
|
||||||
fi
|
|
||||||
|
|
@ -1,480 +0,0 @@
|
||||||
name: "Build: Release"
|
|
||||||
run-name: "Build: Release (${{ github.ref_name }})"
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
build_number_override:
|
|
||||||
description: Optional explicit build number
|
|
||||||
required: false
|
|
||||||
default: ""
|
|
||||||
upload_app_store:
|
|
||||||
description: Trigger downstream App Store Connect upload workflow
|
|
||||||
required: false
|
|
||||||
default: "true"
|
|
||||||
upload_sparkle:
|
|
||||||
description: Trigger downstream Sparkle publish workflow
|
|
||||||
required: false
|
|
||||||
default: "true"
|
|
||||||
upload_microsoft_store:
|
|
||||||
description: Trigger downstream Microsoft Store beta upload workflow
|
|
||||||
required: false
|
|
||||||
default: "false"
|
|
||||||
sparkle_point_main:
|
|
||||||
description: Update Sparkle main channel pointers
|
|
||||||
required: false
|
|
||||||
default: "true"
|
|
||||||
testflight_distribute_external:
|
|
||||||
description: Distribute to external TestFlight groups
|
|
||||||
required: false
|
|
||||||
default: "false"
|
|
||||||
testflight_groups:
|
|
||||||
description: Optional comma-separated TestFlight groups for external distribution
|
|
||||||
required: false
|
|
||||||
default: ""
|
|
||||||
ios_uses_non_exempt_encryption:
|
|
||||||
description: Set true only when the iOS build uses non-exempt encryption
|
|
||||||
required: false
|
|
||||||
default: "false"
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- "release/*"
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
actions: write
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: burrow-build-release-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
env:
|
|
||||||
BURROW_RELEASE_GCS_BUCKET: ${{ vars.BURROW_RELEASE_GCS_BUCKET || 'burrow-net-releases' }}
|
|
||||||
BURROW_RELEASE_GCS_BACKUP: ${{ vars.BURROW_RELEASE_GCS_BACKUP || 'true' }}
|
|
||||||
BURROW_RELEASE_GARAGE_BUCKET: ${{ vars.BURROW_RELEASE_GARAGE_BUCKET || 'burrow-releases' }}
|
|
||||||
BURROW_RELEASE_REQUIRE_GARAGE: ${{ vars.BURROW_RELEASE_REQUIRE_GARAGE || 'true' }}
|
|
||||||
BURROW_GARAGE_ENDPOINT: ${{ vars.BURROW_GARAGE_ENDPOINT || 'https://objects.burrow.net' }}
|
|
||||||
BURROW_GARAGE_REGION: ${{ vars.BURROW_GARAGE_REGION || 'garage' }}
|
|
||||||
AWS_ACCESS_KEY_ID: ${{ secrets.BURROW_GARAGE_ACCESS_KEY_ID }}
|
|
||||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.BURROW_GARAGE_SECRET_ACCESS_KEY }}
|
|
||||||
BURROW_NIX_CACHE_URL: ${{ vars.BURROW_NIX_CACHE_URL || 'https://nix.burrow.net/burrow' }}
|
|
||||||
BURROW_NIX_CACHE_PUBLIC_KEY: ${{ vars.BURROW_NIX_CACHE_PUBLIC_KEY }}
|
|
||||||
BURROW_GOOGLE_PROJECT_ID: ${{ vars.GOOGLE_PROJECT_ID || 'project-88c23ce9-918a-470a-b33' }}
|
|
||||||
GOOGLE_CLOUD_PROJECT: ${{ vars.GOOGLE_PROJECT_ID || 'project-88c23ce9-918a-470a-b33' }}
|
|
||||||
BURROW_GOOGLE_PROJECT_NUMBER: ${{ vars.GOOGLE_PROJECT_NUMBER || '416198671487' }}
|
|
||||||
BURROW_GOOGLE_WIF_POOL_ID: ${{ vars.BURROW_GOOGLE_WIF_POOL_ID || 'burrow-authentik' }}
|
|
||||||
BURROW_GOOGLE_WIF_PROVIDER_ID: ${{ vars.BURROW_GOOGLE_WIF_PROVIDER_ID || 'forgejo-runners' }}
|
|
||||||
BURROW_GOOGLE_WIF_SERVICE_ACCOUNT: ${{ vars.BURROW_GOOGLE_WIF_SERVICE_ACCOUNT || 'burrow-forgejo-runner@project-88c23ce9-918a-470a-b33.iam.gserviceaccount.com' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_ISSUER: ${{ vars.BURROW_AUTHENTIK_WIF_ISSUER || 'https://auth.burrow.net/application/o/google-cloud/' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_AUDIENCE: ${{ vars.BURROW_AUTHENTIK_WIF_AUDIENCE || 'google-wif.burrow.net' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_CLIENT_ID: ${{ vars.BURROW_AUTHENTIK_WIF_CLIENT_ID || 'google-wif.burrow.net' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_CLIENT_SECRET: ${{ secrets.BURROW_AUTHENTIK_WIF_CLIENT_SECRET }}
|
|
||||||
BURROW_APPLE_BUNDLE_ID: ${{ vars.BURROW_APPLE_BUNDLE_ID || 'net.burrow.app' }}
|
|
||||||
BURROW_APPLE_NETWORK_EXTENSION_BUNDLE_ID: ${{ vars.BURROW_APPLE_NETWORK_EXTENSION_BUNDLE_ID || 'net.burrow.app.network' }}
|
|
||||||
BURROW_IOS_DISTRIBUTION_CERTIFICATE_ID: ${{ vars.BURROW_IOS_DISTRIBUTION_CERTIFICATE_ID || '3G42677598' }}
|
|
||||||
BURROW_DEVELOPER_ID_CERTIFICATE_ID: ${{ vars.BURROW_DEVELOPER_ID_CERTIFICATE_ID || '9JKN6HXBHC' }}
|
|
||||||
BURROW_APPLE_CREATE_MISSING_BUNDLE_IDS: ${{ vars.BURROW_APPLE_CREATE_MISSING_BUNDLE_IDS || 'false' }}
|
|
||||||
BURROW_APPLE_ENABLE_CAPABILITIES: ${{ vars.BURROW_APPLE_ENABLE_CAPABILITIES || 'false' }}
|
|
||||||
BURROW_APPLE_SIGNING_MODE: ${{ vars.BURROW_APPLE_SIGNING_MODE || 'google-kms-staged' }}
|
|
||||||
BURROW_NOTARIZE_MACOS: ${{ vars.BURROW_NOTARIZE_MACOS || 'true' }}
|
|
||||||
BURROW_SPARKLE_SIGN_WITH_KMS: ${{ vars.BURROW_SPARKLE_SIGN_WITH_KMS || 'true' }}
|
|
||||||
BURROW_SPARKLE_KMS_KEY: ${{ vars.BURROW_SPARKLE_KMS_KEY || 'sparkle-ed25519' }}
|
|
||||||
BURROW_SPARKLE_KMS_VERSION: ${{ vars.BURROW_SPARKLE_KMS_VERSION || '1' }}
|
|
||||||
BURROW_SPARKLE_FEED_URL: ${{ vars.BURROW_SPARKLE_FEED_URL || 'https://releases.burrow.net/sparkle/appcast.xml' }}
|
|
||||||
BURROW_SPARKLE_PUBLIC_ED_KEY: ${{ vars.BURROW_SPARKLE_PUBLIC_ED_KEY || 'uugZuJeqvvKd91NZ6F1Fv2cQenUbIG/ZW3L9MuaEz30=' }}
|
|
||||||
BURROW_VERSION_REQUIRE_REMOTE: "1"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
prepare:
|
|
||||||
name: Prepare
|
|
||||||
runs-on: namespace-profile-linux-medium
|
|
||||||
outputs:
|
|
||||||
do_release: ${{ steps.plan.outputs.do_release }}
|
|
||||||
build_number: ${{ steps.plan.outputs.build_number }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
with:
|
|
||||||
token: ${{ github.token }}
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Fetch Build Tags
|
|
||||||
shell: bash
|
|
||||||
run: git fetch --force --prune origin "+refs/tags/builds/*:refs/tags/builds/*"
|
|
||||||
|
|
||||||
- name: Compute Release Plan
|
|
||||||
id: plan
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
BURROW_BUILD_NUMBER_OVERRIDE: ${{ github.event.inputs.build_number_override || '' }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
status="$(Scripts/version.sh status)"
|
|
||||||
if [[ "$status" == "clean" ]]; then
|
|
||||||
echo "do_release=false" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "build_number=" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "No unreleased changes."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
build_number="$(Scripts/version.sh pre-increment)"
|
|
||||||
echo "do_release=true" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "build_number=${build_number}" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
build-linux:
|
|
||||||
name: Build (Linux)
|
|
||||||
needs: prepare
|
|
||||||
if: ${{ needs.prepare.outputs.do_release == 'true' }}
|
|
||||||
runs-on: namespace-profile-linux-medium
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
with:
|
|
||||||
token: ${{ github.token }}
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Build Linux Release
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
BUILD_NUMBER: ${{ needs.prepare.outputs.build_number }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
bash Scripts/ci/ensure-nix.sh
|
|
||||||
nix develop .#ci -c Scripts/ci/nscloud-cache.sh nix
|
|
||||||
nix develop .#ci -c Scripts/ci/package-release-artifacts.sh linux
|
|
||||||
|
|
||||||
- name: Upload Linux Artifacts
|
|
||||||
uses: https://code.forgejo.org/actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: burrow-linux-${{ needs.prepare.outputs.build_number }}
|
|
||||||
path: dist/builds/${{ needs.prepare.outputs.build_number }}/linux/*
|
|
||||||
if-no-files-found: error
|
|
||||||
|
|
||||||
- name: Upload Linux Artifacts To Release Storage
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
BUILD_NUMBER: ${{ needs.prepare.outputs.build_number }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
bash Scripts/ci/ensure-nix.sh
|
|
||||||
nix develop .#ci -c Scripts/ci/upload-release-storage.sh
|
|
||||||
|
|
||||||
build-windows:
|
|
||||||
name: Build (Windows Stub)
|
|
||||||
needs: prepare
|
|
||||||
if: ${{ needs.prepare.outputs.do_release == 'true' }}
|
|
||||||
runs-on: namespace-profile-windows-large
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
with:
|
|
||||||
token: ${{ github.token }}
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Build Rust Stub
|
|
||||||
shell: pwsh
|
|
||||||
env:
|
|
||||||
BUILD_NUMBER: ${{ needs.prepare.outputs.build_number }}
|
|
||||||
run: |
|
|
||||||
if (-not (Get-Command cargo -ErrorAction SilentlyContinue)) {
|
|
||||||
Invoke-WebRequest -Uri "https://win.rustup.rs" -OutFile "rustup-init.exe"
|
|
||||||
.\rustup-init.exe -y --profile minimal --default-toolchain stable
|
|
||||||
$env:Path = "$env:USERPROFILE\.cargo\bin;$env:Path"
|
|
||||||
}
|
|
||||||
cargo build --locked --release -p burrow-windows-stub
|
|
||||||
New-Item -ItemType Directory -Force -Path "dist/builds/$env:BUILD_NUMBER/windows/burrow-$env:BUILD_NUMBER-x86_64-pc-windows-msvc" | Out-Null
|
|
||||||
Copy-Item "target/release/burrow.exe" "dist/builds/$env:BUILD_NUMBER/windows/burrow-$env:BUILD_NUMBER-x86_64-pc-windows-msvc/burrow.exe"
|
|
||||||
Copy-Item "README.md" "dist/builds/$env:BUILD_NUMBER/windows/burrow-$env:BUILD_NUMBER-x86_64-pc-windows-msvc/README.md"
|
|
||||||
Compress-Archive -Path "dist/builds/$env:BUILD_NUMBER/windows/burrow-$env:BUILD_NUMBER-x86_64-pc-windows-msvc" -DestinationPath "dist/builds/$env:BUILD_NUMBER/windows/burrow-$env:BUILD_NUMBER-x86_64-pc-windows-msvc.zip" -Force
|
|
||||||
Get-FileHash "dist/builds/$env:BUILD_NUMBER/windows/burrow-$env:BUILD_NUMBER-x86_64-pc-windows-msvc.zip" -Algorithm SHA256 | ForEach-Object { "$($_.Hash.ToLower()) burrow-$env:BUILD_NUMBER-x86_64-pc-windows-msvc.zip" } | Set-Content "dist/builds/$env:BUILD_NUMBER/windows/burrow-$env:BUILD_NUMBER-x86_64-pc-windows-msvc.zip.sha256"
|
|
||||||
|
|
||||||
- name: Upload Windows Artifacts
|
|
||||||
uses: https://code.forgejo.org/actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: burrow-windows-${{ needs.prepare.outputs.build_number }}
|
|
||||||
path: dist/builds/${{ needs.prepare.outputs.build_number }}/windows/*
|
|
||||||
if-no-files-found: error
|
|
||||||
|
|
||||||
build-apple:
|
|
||||||
name: Build (Apple ${{ matrix.platform_name }})
|
|
||||||
needs: prepare
|
|
||||||
if: ${{ needs.prepare.outputs.do_release == 'true' }}
|
|
||||||
runs-on: namespace-profile-macos-large
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
max-parallel: 2
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- platform: ios
|
|
||||||
platform_name: iOS
|
|
||||||
bazel_target: //bazel/apple:release_ios_stamp
|
|
||||||
- platform: macos
|
|
||||||
platform_name: macOS
|
|
||||||
bazel_target: //bazel/apple:release_macos_stamp
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
with:
|
|
||||||
token: ${{ github.token }}
|
|
||||||
fetch-depth: 0
|
|
||||||
submodules: recursive
|
|
||||||
|
|
||||||
- name: Select Apple SDK
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
if ! command -v xcrun >/dev/null 2>&1; then
|
|
||||||
echo "::error ::xcrun is required for Apple release builds" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
xcrun --find swiftc
|
|
||||||
xcrun --sdk macosx --show-sdk-path
|
|
||||||
xcrun --sdk iphoneos --show-sdk-path
|
|
||||||
xcrun --sdk iphonesimulator --show-sdk-path
|
|
||||||
|
|
||||||
- name: Prepare Rust Apple Targets
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
PLATFORM: ${{ matrix.platform }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
if ! command -v rustup >/dev/null 2>&1; then
|
|
||||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain stable
|
|
||||||
export PATH="$HOME/.cargo/bin:$PATH"
|
|
||||||
fi
|
|
||||||
case "$PLATFORM" in
|
|
||||||
ios)
|
|
||||||
rustup target add aarch64-apple-ios aarch64-apple-ios-sim x86_64-apple-ios
|
|
||||||
;;
|
|
||||||
macos)
|
|
||||||
rustup target add aarch64-apple-darwin x86_64-apple-darwin
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "::error ::unsupported Apple platform ${PLATFORM}" >&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
- name: Bootstrap Runner Environment
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
runner_home="${RUNNER_HOME:-}"
|
|
||||||
if [[ -z "$runner_home" ]]; then
|
|
||||||
runner_home="$(python3 -c 'import os,pwd; print(pwd.getpwuid(os.getuid()).pw_dir)' 2>/dev/null || true)"
|
|
||||||
if [[ -z "$runner_home" ]]; then
|
|
||||||
runner_home="$PWD/.home"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
mkdir -p "$runner_home" "$PWD/.tmp"
|
|
||||||
{
|
|
||||||
echo "HOME=$runner_home"
|
|
||||||
echo "XDG_CACHE_HOME=$runner_home/.cache"
|
|
||||||
echo "XDG_CONFIG_HOME=$runner_home/.config"
|
|
||||||
echo "XDG_DATA_HOME=$runner_home/.local/share"
|
|
||||||
echo "TMPDIR=$PWD/.tmp"
|
|
||||||
echo "TMP=$PWD/.tmp"
|
|
||||||
} >> "$GITHUB_ENV"
|
|
||||||
|
|
||||||
- name: Ensure Nix
|
|
||||||
shell: bash
|
|
||||||
run: bash Scripts/ci/ensure-nix.sh
|
|
||||||
|
|
||||||
- name: Namespace Cache
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
NIX_BIN="$(bash Scripts/ci/resolve-nix-bin.sh)"
|
|
||||||
"$NIX_BIN" develop .#ci --command bash Scripts/ci/nscloud-cache.sh bazel
|
|
||||||
|
|
||||||
- name: Configure Age
|
|
||||||
id: age_apple
|
|
||||||
continue-on-error: true
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
AGE_FORGE_SSH_KEY: ${{ secrets.AGE_FORGE_SSH_KEY }}
|
|
||||||
run: Scripts/resolve-age-identity.sh >> "$GITHUB_ENV"
|
|
||||||
|
|
||||||
- name: Decrypt Release Secrets
|
|
||||||
if: ${{ steps.age_apple.outcome == 'success' }}
|
|
||||||
uses: ./.forgejo/actions/decrypt-release-secrets
|
|
||||||
|
|
||||||
- name: Sync Apple Provisioning Profiles
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
PLATFORM: ${{ matrix.platform }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
NIX_BIN="$(bash Scripts/ci/resolve-nix-bin.sh)"
|
|
||||||
"$NIX_BIN" develop .#ci --command Scripts/ci/sync-apple-provisioning-profiles.sh "$PLATFORM"
|
|
||||||
|
|
||||||
- name: Install Apple Signing Assets
|
|
||||||
shell: bash
|
|
||||||
run: Scripts/ci/install-apple-signing-assets.sh
|
|
||||||
|
|
||||||
- name: Build Apple Release
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
BUILD_NUMBER: ${{ needs.prepare.outputs.build_number }}
|
|
||||||
PLATFORM: ${{ matrix.platform }}
|
|
||||||
UPLOAD_APP_STORE: ${{ github.event.inputs.upload_app_store || 'true' }}
|
|
||||||
UPLOAD_SPARKLE: ${{ github.event.inputs.upload_sparkle || 'true' }}
|
|
||||||
SPARKLE_CHANNEL: build-${{ needs.prepare.outputs.build_number }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
require_signing=false
|
|
||||||
if [[ "$UPLOAD_APP_STORE" == "true" && "$PLATFORM" == "ios" ]]; then
|
|
||||||
require_signing=true
|
|
||||||
fi
|
|
||||||
if [[ "$UPLOAD_SPARKLE" == "true" && "$PLATFORM" == "macos" ]]; then
|
|
||||||
require_signing=true
|
|
||||||
fi
|
|
||||||
|
|
||||||
bazel_args=()
|
|
||||||
if [[ -n "${BURROW_BAZEL_NSCCACHE_BAZELRC:-}" && -f "${BURROW_BAZEL_NSCCACHE_BAZELRC:-}" ]]; then
|
|
||||||
bazel_args+=("--bazelrc=${BURROW_BAZEL_NSCCACHE_BAZELRC}")
|
|
||||||
fi
|
|
||||||
|
|
||||||
NIX_BIN="$(bash Scripts/ci/resolve-nix-bin.sh)"
|
|
||||||
ci_path="$("$NIX_BIN" develop .#ci --command bash -lc 'printf "%s" "$PATH"')"
|
|
||||||
ci_protoc="$("$NIX_BIN" develop .#ci --command bash -lc 'command -v protoc')"
|
|
||||||
"$NIX_BIN" develop .#ci --command bazel "${bazel_args[@]}" build \
|
|
||||||
--verbose_failures \
|
|
||||||
--show_timestamps \
|
|
||||||
--experimental_ui_max_stdouterr_bytes=16777216 \
|
|
||||||
--action_env=PATH="$ci_path" \
|
|
||||||
--action_env=PROTOC="$ci_protoc" \
|
|
||||||
--action_env=BUILD_WORKSPACE_DIRECTORY="$PWD" \
|
|
||||||
--action_env=BUILD_NUMBER="$BUILD_NUMBER" \
|
|
||||||
--action_env=BURROW_RELEASE_OUT="$PWD/dist/builds/$BUILD_NUMBER" \
|
|
||||||
--action_env=BURROW_APPLE_SIGNING_READY="${BURROW_APPLE_SIGNING_READY:-0}" \
|
|
||||||
--action_env=BURROW_APPLE_SIGNING_MODE="${BURROW_APPLE_SIGNING_MODE:-keychain}" \
|
|
||||||
--action_env=BURROW_APPLE_REQUIRE_SIGNING="$require_signing" \
|
|
||||||
--action_env=BURROW_APPLE_BUNDLE_ID="${BURROW_APPLE_BUNDLE_ID:-}" \
|
|
||||||
--action_env=BURROW_APPLE_NETWORK_EXTENSION_BUNDLE_ID="${BURROW_APPLE_NETWORK_EXTENSION_BUNDLE_ID:-}" \
|
|
||||||
--action_env=BURROW_APPLE_KEYCHAIN_PATH="${BURROW_APPLE_KEYCHAIN_PATH:-}" \
|
|
||||||
--action_env=BURROW_NOTARIZE_MACOS="${BURROW_NOTARIZE_MACOS:-false}" \
|
|
||||||
--action_env=BURROW_SPARKLE_SIGN_WITH_KMS="${BURROW_SPARKLE_SIGN_WITH_KMS:-false}" \
|
|
||||||
--action_env=BURROW_SPARKLE_KMS_KEY="${BURROW_SPARKLE_KMS_KEY:-sparkle-ed25519}" \
|
|
||||||
--action_env=BURROW_SPARKLE_KMS_VERSION="${BURROW_SPARKLE_KMS_VERSION:-1}" \
|
|
||||||
--action_env=BURROW_SPARKLE_FEED_URL="${BURROW_SPARKLE_FEED_URL:-https://releases.burrow.net/sparkle/appcast.xml}" \
|
|
||||||
--action_env=BURROW_SPARKLE_PUBLIC_ED_KEY="${BURROW_SPARKLE_PUBLIC_ED_KEY:-}" \
|
|
||||||
--action_env=GOOGLE_CLOUD_PROJECT="${GOOGLE_CLOUD_PROJECT:-}" \
|
|
||||||
--action_env=ASC_API_KEY_ID="${ASC_API_KEY_ID:-}" \
|
|
||||||
--action_env=ASC_API_ISSUER_ID="${ASC_API_ISSUER_ID:-}" \
|
|
||||||
--action_env=ASC_API_KEY_PATH="${ASC_API_KEY_PATH:-}" \
|
|
||||||
--action_env=SPARKLE_CHANNEL="$SPARKLE_CHANNEL" \
|
|
||||||
--action_env=HOME="$HOME" \
|
|
||||||
--action_env=XDG_CACHE_HOME="$XDG_CACHE_HOME" \
|
|
||||||
"${{ matrix.bazel_target }}"
|
|
||||||
|
|
||||||
- name: Upload Apple Artifacts
|
|
||||||
uses: https://code.forgejo.org/actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: burrow-apple-${{ matrix.platform }}-${{ needs.prepare.outputs.build_number }}
|
|
||||||
path: |
|
|
||||||
dist/builds/${{ needs.prepare.outputs.build_number }}/apple/*
|
|
||||||
dist/builds/${{ needs.prepare.outputs.build_number }}/sparkle/**
|
|
||||||
if-no-files-found: error
|
|
||||||
|
|
||||||
- name: Upload Apple Artifacts To Release Storage
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
BUILD_NUMBER: ${{ needs.prepare.outputs.build_number }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
bash Scripts/ci/ensure-nix.sh
|
|
||||||
nix develop .#ci -c Scripts/ci/upload-release-storage.sh
|
|
||||||
|
|
||||||
publish:
|
|
||||||
name: Publish (Forgejo)
|
|
||||||
needs:
|
|
||||||
- prepare
|
|
||||||
- build-linux
|
|
||||||
- build-windows
|
|
||||||
- build-apple
|
|
||||||
if: ${{ always() && needs.prepare.outputs.do_release == 'true' }}
|
|
||||||
runs-on: namespace-profile-linux-medium
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
with:
|
|
||||||
token: ${{ github.token }}
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Download Artifacts
|
|
||||||
uses: https://code.forgejo.org/actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
path: dist/downloaded
|
|
||||||
|
|
||||||
- name: Prepare Release Assets
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
BUILD_NUMBER: ${{ needs.prepare.outputs.build_number }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
mkdir -p dist
|
|
||||||
mkdir -p "dist/builds/${BUILD_NUMBER}/windows"
|
|
||||||
find dist/downloaded -path '*/burrow-windows-*/*' -type f -exec cp {} "dist/builds/${BUILD_NUMBER}/windows/" \;
|
|
||||||
find dist/downloaded -type f \( -name '*.tar.gz' -o -name '*.zip' -o -name '*.sha256' -o -name '*.ipa' -o -name '*.pkg' -o -name '*.dmg' -o -name 'README*.txt' \) -exec cp {} dist/ \;
|
|
||||||
rm -rf dist/downloaded
|
|
||||||
find dist -maxdepth 1 -type f -print | sort
|
|
||||||
|
|
||||||
- name: Upload Windows Artifacts To Release Storage
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
BUILD_NUMBER: ${{ needs.prepare.outputs.build_number }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
if ! find "dist/builds/${BUILD_NUMBER}/windows" -type f -print -quit | grep -q .; then
|
|
||||||
echo "::warning ::No Windows artifacts staged for release storage upload."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
bash Scripts/ci/ensure-nix.sh
|
|
||||||
nix develop .#ci -c Scripts/ci/upload-release-storage.sh
|
|
||||||
|
|
||||||
- name: Tag Build
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
BUILD_NUMBER: ${{ needs.prepare.outputs.build_number }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
tag="builds/${BUILD_NUMBER}"
|
|
||||||
head_commit="$(git rev-parse HEAD)"
|
|
||||||
remote_commit="$(git ls-remote --tags --refs origin "refs/tags/${tag}" | awk 'NR==1 { print $1 }')"
|
|
||||||
if [[ -n "$remote_commit" && "$remote_commit" != "$head_commit" ]]; then
|
|
||||||
echo "::error ::Remote tag ${tag} already points at ${remote_commit}, not ${head_commit}" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
git tag -f "$tag" "$head_commit"
|
|
||||||
git push --quiet --no-verify origin "refs/tags/${tag}:refs/tags/${tag}"
|
|
||||||
|
|
||||||
- name: Publish Forgejo Release
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
RELEASE_TAG: builds/${{ needs.prepare.outputs.build_number }}
|
|
||||||
API_URL: ${{ github.api_url }}
|
|
||||||
REPOSITORY: ${{ github.repository }}
|
|
||||||
TOKEN: ${{ github.token }}
|
|
||||||
run: Scripts/ci/publish-forgejo-release.sh
|
|
||||||
|
|
||||||
- name: Dispatch Store Uploads
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ github.token }}
|
|
||||||
BUILD_NUMBER: ${{ needs.prepare.outputs.build_number }}
|
|
||||||
UPLOAD_APP_STORE: ${{ github.event.inputs.upload_app_store || 'true' }}
|
|
||||||
UPLOAD_SPARKLE: ${{ github.event.inputs.upload_sparkle || 'true' }}
|
|
||||||
UPLOAD_MICROSOFT_STORE: ${{ github.event.inputs.upload_microsoft_store || 'false' }}
|
|
||||||
SPARKLE_POINT_MAIN: ${{ github.event.inputs.sparkle_point_main || 'true' }}
|
|
||||||
TESTFLIGHT_DISTRIBUTE_EXTERNAL: ${{ github.event.inputs.testflight_distribute_external || 'false' }}
|
|
||||||
TESTFLIGHT_GROUPS: ${{ github.event.inputs.testflight_groups || '' }}
|
|
||||||
IOS_USES_NON_EXEMPT_ENCRYPTION: ${{ github.event.inputs.ios_uses_non_exempt_encryption || 'false' }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
inputs="$(python3 -c 'import json, os; print(json.dumps({"build_number":os.environ["BUILD_NUMBER"],"upload_app_store":os.environ["UPLOAD_APP_STORE"],"upload_sparkle":os.environ["UPLOAD_SPARKLE"],"upload_microsoft_store":os.environ["UPLOAD_MICROSOFT_STORE"],"sparkle_point_main":os.environ["SPARKLE_POINT_MAIN"],"testflight_distribute_external":os.environ["TESTFLIGHT_DISTRIBUTE_EXTERNAL"],"testflight_groups":os.environ["TESTFLIGHT_GROUPS"],"ios_uses_non_exempt_encryption":os.environ["IOS_USES_NON_EXEMPT_ENCRYPTION"]}))')"
|
|
||||||
curl -fsS \
|
|
||||||
-X POST \
|
|
||||||
-H "Authorization: token ${GITHUB_TOKEN}" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d "{\"ref\":\"main\",\"inputs\":${inputs}}" \
|
|
||||||
"${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/actions/workflows/publish-store-uploads.yml/dispatches"
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
name: Build Rust
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- "**"
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
rust:
|
|
||||||
name: Cargo Test
|
|
||||||
runs-on: [self-hosted, linux, x86_64, burrow-forge]
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
repo_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git"
|
|
||||||
if [ ! -d .git ]; then
|
|
||||||
git init .
|
|
||||||
fi
|
|
||||||
if git remote get-url origin >/dev/null 2>&1; then
|
|
||||||
git remote set-url origin "${repo_url}"
|
|
||||||
else
|
|
||||||
git remote add origin "${repo_url}"
|
|
||||||
fi
|
|
||||||
git fetch --force --tags origin "${GITHUB_SHA}"
|
|
||||||
git checkout --force --detach FETCH_HEAD
|
|
||||||
git clean -ffdqx
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
nix develop .#ci -c cargo test --workspace --all-features
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
name: Build Site
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- "**"
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
site:
|
|
||||||
name: Next.js Build
|
|
||||||
runs-on: [self-hosted, linux, x86_64, burrow-forge]
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
repo_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git"
|
|
||||||
if [ ! -d .git ]; then
|
|
||||||
git init .
|
|
||||||
fi
|
|
||||||
if git remote get-url origin >/dev/null 2>&1; then
|
|
||||||
git remote set-url origin "${repo_url}"
|
|
||||||
else
|
|
||||||
git remote add origin "${repo_url}"
|
|
||||||
fi
|
|
||||||
git fetch --force --tags origin "${GITHUB_SHA}"
|
|
||||||
git checkout --force --detach FETCH_HEAD
|
|
||||||
git clean -ffdqx
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
nix develop .#ci -c bash -lc 'cd site && npm ci --no-audit --no-fund && npm run build'
|
|
||||||
|
|
@ -1,71 +0,0 @@
|
||||||
name: "Apple: Distribute TestFlight"
|
|
||||||
run-name: "Apple: Distribute TestFlight (Build ${{ inputs.build_number }})"
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
build_number:
|
|
||||||
description: Already-uploaded App Store Connect build number
|
|
||||||
required: true
|
|
||||||
testflight_distribute_external:
|
|
||||||
description: Distribute to external TestFlight groups
|
|
||||||
required: false
|
|
||||||
default: "false"
|
|
||||||
testflight_groups:
|
|
||||||
description: Optional comma-separated TestFlight groups
|
|
||||||
required: false
|
|
||||||
default: ""
|
|
||||||
ios_uses_non_exempt_encryption:
|
|
||||||
description: Set true only when the iOS build uses non-exempt encryption
|
|
||||||
required: false
|
|
||||||
default: "false"
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: burrow-distribute-testflight-${{ inputs.build_number }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
env:
|
|
||||||
BURROW_NIX_CACHE_URL: ${{ vars.BURROW_NIX_CACHE_URL || 'https://nix.burrow.net/burrow' }}
|
|
||||||
BURROW_NIX_CACHE_PUBLIC_KEY: ${{ vars.BURROW_NIX_CACHE_PUBLIC_KEY }}
|
|
||||||
BURROW_APPLE_BUNDLE_ID: ${{ vars.BURROW_APPLE_BUNDLE_ID || 'net.burrow.app' }}
|
|
||||||
TESTFLIGHT_WAIT_PROCESSING_TIMEOUT_SECONDS: ${{ vars.TESTFLIGHT_WAIT_PROCESSING_TIMEOUT_SECONDS || '7200' }}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
distribute-ios-testflight:
|
|
||||||
name: Distribute (TestFlight iOS Testers)
|
|
||||||
runs-on: namespace-profile-linux-testflight
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
with:
|
|
||||||
token: ${{ github.token }}
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Ensure Nix
|
|
||||||
shell: bash
|
|
||||||
run: bash Scripts/ci/ensure-nix.sh
|
|
||||||
|
|
||||||
- name: Configure Age
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
AGE_FORGE_SSH_KEY: ${{ secrets.AGE_FORGE_SSH_KEY }}
|
|
||||||
run: Scripts/resolve-age-identity.sh >> "$GITHUB_ENV"
|
|
||||||
|
|
||||||
- name: Decrypt Release Secrets
|
|
||||||
uses: ./.forgejo/actions/decrypt-release-secrets
|
|
||||||
|
|
||||||
- name: Validate App Store Credentials
|
|
||||||
shell: bash
|
|
||||||
run: Scripts/ci/check-release-config.sh app-store
|
|
||||||
|
|
||||||
- name: Distribute iOS Build To TestFlight
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
BUILD_NUMBER: ${{ inputs.build_number }}
|
|
||||||
TESTFLIGHT_DISTRIBUTE_EXTERNAL: ${{ inputs.testflight_distribute_external || 'false' }}
|
|
||||||
TESTFLIGHT_GROUPS: ${{ inputs.testflight_groups || '' }}
|
|
||||||
IOS_USES_NON_EXEMPT_ENCRYPTION: ${{ inputs.ios_uses_non_exempt_encryption || 'false' }}
|
|
||||||
run: Scripts/ci/distribute-testflight.sh
|
|
||||||
|
|
@ -1,237 +0,0 @@
|
||||||
name: "Infra: OpenTofu"
|
|
||||||
run-name: "Infra: OpenTofu (${{ github.event.inputs.stack || 'grafana' }} ${{ github.event.inputs.mode || 'validate' }})"
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths:
|
|
||||||
- ".forgejo/workflows/infra-opentofu.yml"
|
|
||||||
- "Scripts/grafana-tofu.sh"
|
|
||||||
- "Scripts/identity-tofu.sh"
|
|
||||||
- "Scripts/openbao-tofu.sh"
|
|
||||||
- "Scripts/releases-tofu.sh"
|
|
||||||
- "infra/grafana/**"
|
|
||||||
- "infra/identity/**"
|
|
||||||
- "infra/openbao/**"
|
|
||||||
- "infra/releases/**"
|
|
||||||
- "services/grafana/**"
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
stack:
|
|
||||||
description: OpenTofu stack to run
|
|
||||||
required: true
|
|
||||||
default: grafana
|
|
||||||
type: choice
|
|
||||||
options:
|
|
||||||
- grafana
|
|
||||||
- identity
|
|
||||||
- openbao
|
|
||||||
- releases
|
|
||||||
mode:
|
|
||||||
description: OpenTofu mode
|
|
||||||
required: true
|
|
||||||
default: plan
|
|
||||||
type: choice
|
|
||||||
options:
|
|
||||||
- fmt
|
|
||||||
- validate
|
|
||||||
- plan
|
|
||||||
- apply
|
|
||||||
- import
|
|
||||||
apply_confirmation:
|
|
||||||
description: Type apply-burrow-<stack>-tofu to run apply
|
|
||||||
required: false
|
|
||||||
default: ""
|
|
||||||
import_address:
|
|
||||||
description: OpenTofu resource address for import mode
|
|
||||||
required: false
|
|
||||||
default: ""
|
|
||||||
import_id:
|
|
||||||
description: Provider import id for import mode
|
|
||||||
required: false
|
|
||||||
default: ""
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: infra-opentofu-${{ github.ref }}-${{ github.event.inputs.stack || 'grafana' }}
|
|
||||||
cancel-in-progress: false
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
opentofu:
|
|
||||||
name: OpenTofu (${{ github.event.inputs.stack || 'grafana' }})
|
|
||||||
runs-on: [self-hosted, linux, x86_64, burrow-forge]
|
|
||||||
timeout-minutes: 30
|
|
||||||
env:
|
|
||||||
MODE: ${{ github.event.inputs.mode || 'validate' }}
|
|
||||||
STACK: ${{ github.event.inputs.stack || 'grafana' }}
|
|
||||||
APPLY_CONFIRMATION: ${{ github.event.inputs.apply_confirmation || '' }}
|
|
||||||
IMPORT_ADDRESS: ${{ github.event.inputs.import_address || '' }}
|
|
||||||
IMPORT_ID: ${{ github.event.inputs.import_id || '' }}
|
|
||||||
TF_INPUT: "false"
|
|
||||||
TF_IN_AUTOMATION: "true"
|
|
||||||
TF_VAR_grafana_url: ${{ vars.GRAFANA_URL || 'https://graphs.burrow.net' }}
|
|
||||||
TF_VAR_google_project_id: ${{ vars.GOOGLE_PROJECT_ID || 'project-88c23ce9-918a-470a-b33' }}
|
|
||||||
TF_VAR_google_project_number: ${{ vars.GOOGLE_PROJECT_NUMBER || '416198671487' }}
|
|
||||||
TF_VAR_google_runner_service_account_email: ${{ vars.BURROW_GOOGLE_WIF_SERVICE_ACCOUNT || 'burrow-forgejo-runner@project-88c23ce9-918a-470a-b33.iam.gserviceaccount.com' }}
|
|
||||||
TF_VAR_google_wif_runner_client_id: ${{ vars.BURROW_AUTHENTIK_WIF_CLIENT_ID || 'google-wif.burrow.net' }}
|
|
||||||
TF_VAR_google_release_bucket_name: ${{ vars.BURROW_RELEASE_GCS_BUCKET || 'burrow-net-releases' }}
|
|
||||||
TF_VAR_google_package_bucket_name: ${{ vars.BURROW_PACKAGE_GCS_BUCKET || 'burrow-net-packages' }}
|
|
||||||
TF_VAR_google_nix_cache_bucket_name: ${{ vars.BURROW_NIX_CACHE_GCS_BUCKET || 'burrow-net-nix-cache' }}
|
|
||||||
TF_VAR_google_nix_cache_public_read: ${{ vars.BURROW_NIX_CACHE_GCS_PUBLIC_READ || 'false' }}
|
|
||||||
TF_VAR_google_storage_location: ${{ vars.BURROW_GCS_LOCATION || 'US' }}
|
|
||||||
BURROW_GOOGLE_PROJECT_ID: ${{ vars.GOOGLE_PROJECT_ID || 'project-88c23ce9-918a-470a-b33' }}
|
|
||||||
GOOGLE_CLOUD_PROJECT: ${{ vars.GOOGLE_PROJECT_ID || 'project-88c23ce9-918a-470a-b33' }}
|
|
||||||
BURROW_GOOGLE_PROJECT_NUMBER: ${{ vars.GOOGLE_PROJECT_NUMBER || '416198671487' }}
|
|
||||||
BURROW_GOOGLE_WIF_POOL_ID: ${{ vars.BURROW_GOOGLE_WIF_POOL_ID || 'burrow-authentik' }}
|
|
||||||
BURROW_GOOGLE_WIF_PROVIDER_ID: ${{ vars.BURROW_GOOGLE_WIF_PROVIDER_ID || 'forgejo-runners' }}
|
|
||||||
BURROW_GOOGLE_WIF_SERVICE_ACCOUNT: ${{ vars.BURROW_GOOGLE_WIF_SERVICE_ACCOUNT || 'burrow-forgejo-runner@project-88c23ce9-918a-470a-b33.iam.gserviceaccount.com' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_ISSUER: ${{ vars.BURROW_AUTHENTIK_WIF_ISSUER || 'https://auth.burrow.net/application/o/google-cloud/' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_AUDIENCE: ${{ vars.BURROW_AUTHENTIK_WIF_AUDIENCE || 'google-wif.burrow.net' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_CLIENT_ID: ${{ vars.BURROW_AUTHENTIK_WIF_CLIENT_ID || 'google-wif.burrow.net' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_CLIENT_SECRET: ${{ secrets.BURROW_AUTHENTIK_WIF_CLIENT_SECRET }}
|
|
||||||
BURROW_NIX_CACHE_URL: ${{ vars.BURROW_NIX_CACHE_URL || 'https://nix.burrow.net/burrow' }}
|
|
||||||
BURROW_NIX_CACHE_PUBLIC_KEY: ${{ vars.BURROW_NIX_CACHE_PUBLIC_KEY }}
|
|
||||||
OPENTOFU_STATE_BUCKET: ${{ vars.OPENTOFU_STATE_BUCKET || '' }}
|
|
||||||
OPENTOFU_STATE_REGION: ${{ vars.OPENTOFU_STATE_REGION || vars.AWS_REGION || 'us-west-2' }}
|
|
||||||
OPENTOFU_STATE_DYNAMODB_TABLE: ${{ vars.OPENTOFU_STATE_DYNAMODB_TABLE || '' }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
repo_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git"
|
|
||||||
if [ ! -d .git ]; then
|
|
||||||
git init .
|
|
||||||
fi
|
|
||||||
if git remote get-url origin >/dev/null 2>&1; then
|
|
||||||
git remote set-url origin "${repo_url}"
|
|
||||||
else
|
|
||||||
git remote add origin "${repo_url}"
|
|
||||||
fi
|
|
||||||
git fetch --force --tags origin "${GITHUB_SHA}"
|
|
||||||
git checkout --force --detach FETCH_HEAD
|
|
||||||
git clean -ffdqx
|
|
||||||
|
|
||||||
- name: Validate Request
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
case "$STACK" in
|
|
||||||
grafana|identity|openbao|releases) ;;
|
|
||||||
*)
|
|
||||||
echo "::error ::Unsupported OpenTofu stack: $STACK" >&2
|
|
||||||
exit 2
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
case "$MODE" in
|
|
||||||
fmt|validate|plan|apply|import) ;;
|
|
||||||
*)
|
|
||||||
echo "::error ::Unsupported OpenTofu mode: $MODE" >&2
|
|
||||||
exit 2
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [[ "${GITHUB_EVENT_NAME}" != "workflow_dispatch" && "$MODE" != "validate" ]]; then
|
|
||||||
echo "::error ::Non-manual runs may only validate." >&2
|
|
||||||
exit 2
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$MODE" == "apply" && "$APPLY_CONFIRMATION" != "apply-burrow-${STACK}-tofu" ]]; then
|
|
||||||
echo "::error ::apply_confirmation must be exactly apply-burrow-${STACK}-tofu." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$MODE" == "import" && ( -z "$IMPORT_ADDRESS" || -z "$IMPORT_ID" ) ]]; then
|
|
||||||
echo "::error ::import mode requires import_address and import_id." >&2
|
|
||||||
exit 2
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Configure Age
|
|
||||||
if: ${{ github.event_name == 'workflow_dispatch' && (github.event.inputs.mode == 'plan' || github.event.inputs.mode == 'apply' || github.event.inputs.mode == 'import') }}
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
AGE_FORGE_SSH_KEY: ${{ secrets.AGE_FORGE_SSH_KEY }}
|
|
||||||
run: Scripts/resolve-age-identity.sh >> "$GITHUB_ENV"
|
|
||||||
|
|
||||||
- name: Configure Grafana Provider Auth
|
|
||||||
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.stack == 'grafana' && (github.event.inputs.mode == 'plan' || github.event.inputs.mode == 'apply' || github.event.inputs.mode == 'import') }}
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
: "${AGE_IDENTITY_PATH:?AGE_IDENTITY_PATH is required}"
|
|
||||||
agenix="$(nix build --no-link .#agenix --print-out-paths | tail -n1)/bin/agenix"
|
|
||||||
password="$("$agenix" --identity "$AGE_IDENTITY_PATH" --decrypt secrets/infra/grafana-admin-password.age | tr -d '\r')"
|
|
||||||
|
|
||||||
echo "::add-mask::${password}"
|
|
||||||
{
|
|
||||||
echo "TF_VAR_grafana_auth<<EOF"
|
|
||||||
printf 'admin:%s\n' "$password"
|
|
||||||
echo "EOF"
|
|
||||||
} >> "$GITHUB_ENV"
|
|
||||||
|
|
||||||
- name: Configure OpenTofu Backend
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
stack_dir="infra/${STACK}"
|
|
||||||
rm -f "${stack_dir}/backend.hcl"
|
|
||||||
if [[ -n "$OPENTOFU_STATE_BUCKET" ]]; then
|
|
||||||
{
|
|
||||||
printf 'bucket = "%s"\n' "$OPENTOFU_STATE_BUCKET"
|
|
||||||
printf 'key = "%s"\n' "${STACK}/${STACK}.tfstate"
|
|
||||||
printf 'region = "%s"\n' "$OPENTOFU_STATE_REGION"
|
|
||||||
printf 'encrypt = true\n'
|
|
||||||
if [[ -n "$OPENTOFU_STATE_DYNAMODB_TABLE" ]]; then
|
|
||||||
printf 'dynamodb_table = "%s"\n' "$OPENTOFU_STATE_DYNAMODB_TABLE"
|
|
||||||
fi
|
|
||||||
} > "${stack_dir}/backend.hcl"
|
|
||||||
elif [[ "$MODE" == "apply" || "$MODE" == "import" ]]; then
|
|
||||||
echo "::error ::OPENTOFU_STATE_BUCKET is required for apply/import." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Authenticate Google WIF
|
|
||||||
if: ${{ github.event_name == 'workflow_dispatch' && (github.event.inputs.stack == 'identity' || github.event.inputs.stack == 'releases') && (github.event.inputs.mode == 'plan' || github.event.inputs.mode == 'apply' || github.event.inputs.mode == 'import') }}
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
nix develop .#ci -c Scripts/ci/google-wif-auth.sh
|
|
||||||
|
|
||||||
- name: Run OpenTofu
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
stack_script="Scripts/${STACK}-tofu.sh"
|
|
||||||
case "$MODE" in
|
|
||||||
fmt)
|
|
||||||
nix develop .#ci -c tofu -chdir="infra/${STACK}" fmt -check
|
|
||||||
;;
|
|
||||||
validate)
|
|
||||||
"$stack_script" init -backend=false
|
|
||||||
"$stack_script" validate
|
|
||||||
;;
|
|
||||||
plan)
|
|
||||||
if [[ -f "infra/${STACK}/backend.hcl" ]]; then
|
|
||||||
"$stack_script" init -backend-config=backend.hcl
|
|
||||||
else
|
|
||||||
"$stack_script" init -backend=false
|
|
||||||
fi
|
|
||||||
"$stack_script" plan
|
|
||||||
;;
|
|
||||||
apply)
|
|
||||||
"$stack_script" init -backend-config=backend.hcl
|
|
||||||
"$stack_script" apply -auto-approve
|
|
||||||
;;
|
|
||||||
import)
|
|
||||||
"$stack_script" init -backend-config=backend.hcl
|
|
||||||
"$stack_script" import "$IMPORT_ADDRESS" "$IMPORT_ID"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
name: Lint Governance
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- "**"
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
governance:
|
|
||||||
name: BEP Metadata
|
|
||||||
runs-on: [self-hosted, linux, x86_64, burrow-forge]
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
repo_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git"
|
|
||||||
if [ ! -d .git ]; then
|
|
||||||
git init .
|
|
||||||
fi
|
|
||||||
if git remote get-url origin >/dev/null 2>&1; then
|
|
||||||
git remote set-url origin "${repo_url}"
|
|
||||||
else
|
|
||||||
git remote add origin "${repo_url}"
|
|
||||||
fi
|
|
||||||
git fetch --force --tags origin "${GITHUB_SHA}"
|
|
||||||
git checkout --force --detach FETCH_HEAD
|
|
||||||
git clean -ffdqx
|
|
||||||
|
|
||||||
- name: Validate BEP metadata
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
python3 Scripts/check-bep-metadata.py
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
name: "Cache: Publish Nix"
|
|
||||||
run-name: "Publish Nix Cache (${{ github.ref_name }})"
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths:
|
|
||||||
- ".forgejo/workflows/publish-nix-cache.yml"
|
|
||||||
- "Cargo.lock"
|
|
||||||
- "Cargo.toml"
|
|
||||||
- "flake.lock"
|
|
||||||
- "flake.nix"
|
|
||||||
- "crates/**"
|
|
||||||
- "services/forgejo-nsc/**"
|
|
||||||
- "nixos/**"
|
|
||||||
- "Scripts/ci/ensure-nix.sh"
|
|
||||||
- "Scripts/ci/publish-nix-cache.sh"
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
attrs:
|
|
||||||
description: Space-separated flake attrs to build and push
|
|
||||||
required: false
|
|
||||||
default: ".#burrow .#forgejo-nsc-dispatcher .#forgejo-nsc-autoscaler"
|
|
||||||
required:
|
|
||||||
description: Fail when the cache push token is missing
|
|
||||||
required: false
|
|
||||||
default: "false"
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: publish-nix-cache-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
publish:
|
|
||||||
name: Publish Nix Cache
|
|
||||||
runs-on: namespace-profile-linux-medium
|
|
||||||
timeout-minutes: 45
|
|
||||||
env:
|
|
||||||
BURROW_NIX_CACHE_SERVER_NAME: ${{ vars.BURROW_NIX_CACHE_SERVER_NAME || 'burrow' }}
|
|
||||||
BURROW_NIX_CACHE_SERVER_URL: ${{ vars.BURROW_NIX_CACHE_SERVER_URL || 'https://nix.burrow.net' }}
|
|
||||||
BURROW_NIX_CACHE_NAME: ${{ vars.BURROW_NIX_CACHE_NAME || 'burrow' }}
|
|
||||||
BURROW_NIX_CACHE_URL: ${{ vars.BURROW_NIX_CACHE_URL || 'https://nix.burrow.net/burrow' }}
|
|
||||||
BURROW_NIX_CACHE_PUBLIC_KEY: ${{ vars.BURROW_NIX_CACHE_PUBLIC_KEY }}
|
|
||||||
BURROW_NIX_CACHE_PUSH_TOKEN: ${{ secrets.BURROW_NIX_CACHE_PUSH_TOKEN }}
|
|
||||||
BURROW_NIX_CACHE_ATTRS: ${{ github.event.inputs.attrs || '.#burrow .#forgejo-nsc-dispatcher .#forgejo-nsc-autoscaler' }}
|
|
||||||
BURROW_NIX_CACHE_REQUIRED: ${{ github.event.inputs.required || 'false' }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Ensure Nix
|
|
||||||
shell: bash
|
|
||||||
run: bash Scripts/ci/ensure-nix.sh
|
|
||||||
|
|
||||||
- name: Publish Cache Paths
|
|
||||||
shell: bash
|
|
||||||
run: nix develop .#ci -c Scripts/ci/publish-nix-cache.sh
|
|
||||||
|
|
@ -1,148 +0,0 @@
|
||||||
name: "Publish: Package Repositories"
|
|
||||||
run-name: "Publish Package Repositories (${{ github.event.inputs.channel || 'stable' }})"
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
build_number:
|
|
||||||
description: Build number or release label for package artifact paths
|
|
||||||
required: false
|
|
||||||
default: ""
|
|
||||||
channel:
|
|
||||||
description: Native package repository channel
|
|
||||||
required: true
|
|
||||||
default: stable
|
|
||||||
type: choice
|
|
||||||
options:
|
|
||||||
- stable
|
|
||||||
- beta
|
|
||||||
- nightly
|
|
||||||
publish_gcs:
|
|
||||||
description: Publish repository tree to configured package storage targets
|
|
||||||
required: false
|
|
||||||
default: "true"
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: publish-package-repositories-${{ github.ref }}-${{ github.event.inputs.channel || 'stable' }}
|
|
||||||
cancel-in-progress: false
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
publish:
|
|
||||||
name: Build Native Repositories
|
|
||||||
runs-on: [self-hosted, linux, x86_64, burrow-forge]
|
|
||||||
timeout-minutes: 45
|
|
||||||
env:
|
|
||||||
BUILD_NUMBER: ${{ github.event.inputs.build_number || github.sha }}
|
|
||||||
BURROW_PACKAGE_CHANNEL: ${{ github.event.inputs.channel || 'stable' }}
|
|
||||||
BURROW_KMS_LOCATION: ${{ vars.BURROW_KMS_LOCATION || 'global' }}
|
|
||||||
BURROW_KMS_KEYRING: ${{ vars.BURROW_KMS_KEYRING || 'burrow-identity' }}
|
|
||||||
BURROW_KMS_VERSION: ${{ vars.BURROW_KMS_VERSION || '1' }}
|
|
||||||
BURROW_GOOGLE_PROJECT_ID: ${{ vars.GOOGLE_PROJECT_ID || 'project-88c23ce9-918a-470a-b33' }}
|
|
||||||
GOOGLE_CLOUD_PROJECT: ${{ vars.GOOGLE_PROJECT_ID || 'project-88c23ce9-918a-470a-b33' }}
|
|
||||||
BURROW_GOOGLE_PROJECT_NUMBER: ${{ vars.GOOGLE_PROJECT_NUMBER || '416198671487' }}
|
|
||||||
BURROW_GOOGLE_WIF_POOL_ID: ${{ vars.BURROW_GOOGLE_WIF_POOL_ID || 'burrow-authentik' }}
|
|
||||||
BURROW_GOOGLE_WIF_PROVIDER_ID: ${{ vars.BURROW_GOOGLE_WIF_PROVIDER_ID || 'forgejo-runners' }}
|
|
||||||
BURROW_GOOGLE_WIF_SERVICE_ACCOUNT: ${{ vars.BURROW_GOOGLE_WIF_SERVICE_ACCOUNT || 'burrow-forgejo-runner@project-88c23ce9-918a-470a-b33.iam.gserviceaccount.com' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_ISSUER: ${{ vars.BURROW_AUTHENTIK_WIF_ISSUER || 'https://auth.burrow.net/application/o/google-cloud/' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_AUDIENCE: ${{ vars.BURROW_AUTHENTIK_WIF_AUDIENCE || 'google-wif.burrow.net' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_CLIENT_ID: ${{ vars.BURROW_AUTHENTIK_WIF_CLIENT_ID || 'google-wif.burrow.net' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_CLIENT_SECRET: ${{ secrets.BURROW_AUTHENTIK_WIF_CLIENT_SECRET }}
|
|
||||||
BURROW_PACKAGE_GCS_BUCKET: ${{ vars.BURROW_PACKAGE_GCS_BUCKET || 'burrow-net-packages' }}
|
|
||||||
BURROW_PACKAGE_GCS_PREFIX: ${{ vars.BURROW_PACKAGE_GCS_PREFIX || '' }}
|
|
||||||
BURROW_PACKAGE_GCS_BACKUP: ${{ vars.BURROW_PACKAGE_GCS_BACKUP || 'true' }}
|
|
||||||
BURROW_PACKAGE_GARAGE_BUCKET: ${{ vars.BURROW_PACKAGE_GARAGE_BUCKET || 'burrow-packages' }}
|
|
||||||
BURROW_PACKAGE_GARAGE_PREFIX: ${{ vars.BURROW_PACKAGE_GARAGE_PREFIX || vars.BURROW_PACKAGE_GCS_PREFIX || '' }}
|
|
||||||
BURROW_PACKAGE_REQUIRE_GARAGE: ${{ vars.BURROW_PACKAGE_REQUIRE_GARAGE || 'true' }}
|
|
||||||
BURROW_GARAGE_ENDPOINT: ${{ vars.BURROW_GARAGE_ENDPOINT || 'https://objects.burrow.net' }}
|
|
||||||
BURROW_GARAGE_REGION: ${{ vars.BURROW_GARAGE_REGION || 'garage' }}
|
|
||||||
AWS_ACCESS_KEY_ID: ${{ secrets.BURROW_GARAGE_ACCESS_KEY_ID }}
|
|
||||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.BURROW_GARAGE_SECRET_ACCESS_KEY }}
|
|
||||||
BURROW_NIX_CACHE_URL: ${{ vars.BURROW_NIX_CACHE_URL || 'https://nix.burrow.net/burrow' }}
|
|
||||||
BURROW_NIX_CACHE_PUBLIC_KEY: ${{ vars.BURROW_NIX_CACHE_PUBLIC_KEY }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
repo_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git"
|
|
||||||
if [ ! -d .git ]; then
|
|
||||||
git init .
|
|
||||||
fi
|
|
||||||
if git remote get-url origin >/dev/null 2>&1; then
|
|
||||||
git remote set-url origin "${repo_url}"
|
|
||||||
else
|
|
||||||
git remote add origin "${repo_url}"
|
|
||||||
fi
|
|
||||||
git fetch --force --tags origin "${GITHUB_SHA}"
|
|
||||||
git checkout --force --detach FETCH_HEAD
|
|
||||||
git clean -ffdqx
|
|
||||||
|
|
||||||
- name: Ensure Nix
|
|
||||||
shell: bash
|
|
||||||
run: bash Scripts/ci/ensure-nix.sh
|
|
||||||
|
|
||||||
- name: Build Linux Packages
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
export BURROW_RELEASE_OUT="$PWD/dist/builds/$BUILD_NUMBER"
|
|
||||||
nix develop .#ci -c Scripts/ci/package-release-artifacts.sh linux
|
|
||||||
|
|
||||||
- name: Authenticate Google WIF
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
nix develop .#ci -c Scripts/ci/google-wif-auth.sh
|
|
||||||
|
|
||||||
- name: Export KMS Public Keys
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
mkdir -p "$PWD/.kms"
|
|
||||||
|
|
||||||
export BURROW_APT_REPO_KMS_KEY="${BURROW_APT_REPO_KMS_KEY:-package-apt-repository}"
|
|
||||||
export BURROW_RPM_REPO_KMS_KEY="${BURROW_RPM_REPO_KMS_KEY:-package-rpm-repository}"
|
|
||||||
export BURROW_PACMAN_REPO_KMS_KEY="${BURROW_PACMAN_REPO_KMS_KEY:-package-pacman-repository}"
|
|
||||||
|
|
||||||
for item in \
|
|
||||||
"APT:${BURROW_APT_REPO_KMS_KEY}:apt" \
|
|
||||||
"RPM:${BURROW_RPM_REPO_KMS_KEY}:rpm" \
|
|
||||||
"PACMAN:${BURROW_PACMAN_REPO_KMS_KEY}:pacman"
|
|
||||||
do
|
|
||||||
IFS=: read -r env_prefix key_name file_prefix <<< "$item"
|
|
||||||
pem="$PWD/.kms/${file_prefix}.pem"
|
|
||||||
nix develop .#ci -c gcloud kms keys versions get-public-key "$BURROW_KMS_VERSION" \
|
|
||||||
--location "$BURROW_KMS_LOCATION" \
|
|
||||||
--keyring "$BURROW_KMS_KEYRING" \
|
|
||||||
--key "$key_name" \
|
|
||||||
--project "$GOOGLE_CLOUD_PROJECT" \
|
|
||||||
--output-file "$pem"
|
|
||||||
echo "BURROW_${env_prefix}_REPO_KMS_PUBLIC_KEY_PEM=$pem" >> "$GITHUB_ENV"
|
|
||||||
echo "BURROW_${env_prefix}_REPO_KMS_KEY=$key_name" >> "$GITHUB_ENV"
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: Build Repository Metadata
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
export BURROW_PACKAGE_INPUT_DIR="$PWD/dist/builds/$BUILD_NUMBER/linux"
|
|
||||||
export BURROW_PACKAGE_REPOSITORY_DIR="$PWD/dist/builds/$BUILD_NUMBER/repositories"
|
|
||||||
nix develop .#ci -c Scripts/package/build-repositories.sh all
|
|
||||||
|
|
||||||
- name: Upload Repository Artifact
|
|
||||||
uses: https://code.forgejo.org/actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: burrow-package-repositories-${{ github.event.inputs.channel || 'stable' }}-${{ github.event.inputs.build_number || github.sha }}
|
|
||||||
path: dist/builds/${{ github.event.inputs.build_number || github.sha }}/repositories/**
|
|
||||||
if-no-files-found: error
|
|
||||||
|
|
||||||
- name: Publish Package Repository To Storage
|
|
||||||
if: ${{ github.event.inputs.publish_gcs == 'true' }}
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
export BURROW_PACKAGE_REPOSITORY_DIR="$PWD/dist/builds/$BUILD_NUMBER/repositories"
|
|
||||||
nix develop .#ci -c Scripts/ci/upload-package-storage.sh
|
|
||||||
|
|
@ -1,385 +0,0 @@
|
||||||
name: "Publish: Release Uploads"
|
|
||||||
run-name: "Publish: Release Uploads (Build ${{ inputs.build_number }})"
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
build_number:
|
|
||||||
description: Build number to publish
|
|
||||||
required: true
|
|
||||||
upload_app_store:
|
|
||||||
description: Upload iOS/macOS/visionOS artifacts to App Store Connect
|
|
||||||
required: false
|
|
||||||
default: "true"
|
|
||||||
distribute_testflight:
|
|
||||||
description: Distribute an already-uploaded iOS build to TestFlight
|
|
||||||
required: false
|
|
||||||
default: "false"
|
|
||||||
upload_sparkle:
|
|
||||||
description: Publish Sparkle artifacts
|
|
||||||
required: false
|
|
||||||
default: "true"
|
|
||||||
upload_microsoft_store:
|
|
||||||
description: Upload Windows package to Microsoft Partner Center beta lane
|
|
||||||
required: false
|
|
||||||
default: "false"
|
|
||||||
sparkle_channel:
|
|
||||||
description: Sparkle channel, defaults to build-<number>
|
|
||||||
required: false
|
|
||||||
default: ""
|
|
||||||
sparkle_point_main:
|
|
||||||
description: Point Sparkle main appcast/default channel to selected channel
|
|
||||||
required: false
|
|
||||||
default: "true"
|
|
||||||
testflight_distribute_external:
|
|
||||||
description: Distribute to external TestFlight groups
|
|
||||||
required: false
|
|
||||||
default: "false"
|
|
||||||
testflight_groups:
|
|
||||||
description: Optional comma-separated TestFlight groups for external distribution
|
|
||||||
required: false
|
|
||||||
default: ""
|
|
||||||
ios_uses_non_exempt_encryption:
|
|
||||||
description: Set true only when the iOS build uses non-exempt encryption
|
|
||||||
required: false
|
|
||||||
default: "false"
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: burrow-publish-store-uploads-${{ inputs.build_number }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
env:
|
|
||||||
BURROW_RELEASE_GCS_BUCKET: ${{ vars.BURROW_RELEASE_GCS_BUCKET || 'burrow-net-releases' }}
|
|
||||||
BURROW_GOOGLE_PROJECT_ID: ${{ vars.GOOGLE_PROJECT_ID || 'project-88c23ce9-918a-470a-b33' }}
|
|
||||||
GOOGLE_CLOUD_PROJECT: ${{ vars.GOOGLE_PROJECT_ID || 'project-88c23ce9-918a-470a-b33' }}
|
|
||||||
BURROW_GOOGLE_PROJECT_NUMBER: ${{ vars.GOOGLE_PROJECT_NUMBER || '416198671487' }}
|
|
||||||
BURROW_GOOGLE_WIF_POOL_ID: ${{ vars.BURROW_GOOGLE_WIF_POOL_ID || 'burrow-authentik' }}
|
|
||||||
BURROW_GOOGLE_WIF_PROVIDER_ID: ${{ vars.BURROW_GOOGLE_WIF_PROVIDER_ID || 'forgejo-runners' }}
|
|
||||||
BURROW_GOOGLE_WIF_SERVICE_ACCOUNT: ${{ vars.BURROW_GOOGLE_WIF_SERVICE_ACCOUNT || 'burrow-forgejo-runner@project-88c23ce9-918a-470a-b33.iam.gserviceaccount.com' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_ISSUER: ${{ vars.BURROW_AUTHENTIK_WIF_ISSUER || 'https://auth.burrow.net/application/o/google-cloud/' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_AUDIENCE: ${{ vars.BURROW_AUTHENTIK_WIF_AUDIENCE || 'google-wif.burrow.net' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_CLIENT_ID: ${{ vars.BURROW_AUTHENTIK_WIF_CLIENT_ID || 'google-wif.burrow.net' }}
|
|
||||||
BURROW_AUTHENTIK_WIF_CLIENT_SECRET: ${{ secrets.BURROW_AUTHENTIK_WIF_CLIENT_SECRET }}
|
|
||||||
BURROW_NIX_CACHE_URL: ${{ vars.BURROW_NIX_CACHE_URL || 'https://nix.burrow.net/burrow' }}
|
|
||||||
BURROW_NIX_CACHE_PUBLIC_KEY: ${{ vars.BURROW_NIX_CACHE_PUBLIC_KEY }}
|
|
||||||
BURROW_APPLE_BUNDLE_ID: ${{ vars.BURROW_APPLE_BUNDLE_ID || 'net.burrow.app' }}
|
|
||||||
BURROW_APPLE_NETWORK_EXTENSION_BUNDLE_ID: ${{ vars.BURROW_APPLE_NETWORK_EXTENSION_BUNDLE_ID || 'net.burrow.app.network' }}
|
|
||||||
BURROW_IOS_DISTRIBUTION_CERTIFICATE_ID: ${{ vars.BURROW_IOS_DISTRIBUTION_CERTIFICATE_ID || '3G42677598' }}
|
|
||||||
BURROW_DEVELOPER_ID_CERTIFICATE_ID: ${{ vars.BURROW_DEVELOPER_ID_CERTIFICATE_ID || '9JKN6HXBHC' }}
|
|
||||||
BURROW_APPLE_SIGNING_MODE: ${{ vars.BURROW_APPLE_SIGNING_MODE || 'google-kms-staged' }}
|
|
||||||
BURROW_NOTARIZE_MACOS: ${{ vars.BURROW_NOTARIZE_MACOS || 'true' }}
|
|
||||||
BURROW_SPARKLE_SIGN_WITH_KMS: ${{ vars.BURROW_SPARKLE_SIGN_WITH_KMS || 'true' }}
|
|
||||||
BURROW_SPARKLE_KMS_KEY: ${{ vars.BURROW_SPARKLE_KMS_KEY || 'sparkle-ed25519' }}
|
|
||||||
BURROW_SPARKLE_KMS_VERSION: ${{ vars.BURROW_SPARKLE_KMS_VERSION || '1' }}
|
|
||||||
BURROW_KMS_LOCATION: ${{ vars.BURROW_KMS_LOCATION || 'global' }}
|
|
||||||
BURROW_KMS_KEYRING: ${{ vars.BURROW_KMS_KEYRING || 'burrow-identity' }}
|
|
||||||
TESTFLIGHT_WAIT_PROCESSING_TIMEOUT_SECONDS: ${{ vars.TESTFLIGHT_WAIT_PROCESSING_TIMEOUT_SECONDS || '7200' }}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
sign-apple-kms:
|
|
||||||
name: Sign (Apple KMS)
|
|
||||||
if: ${{ inputs.upload_app_store == 'true' || inputs.upload_sparkle == 'true' }}
|
|
||||||
runs-on: namespace-profile-linux-medium
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
with:
|
|
||||||
token: ${{ github.token }}
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Ensure Nix
|
|
||||||
shell: bash
|
|
||||||
run: bash Scripts/ci/ensure-nix.sh
|
|
||||||
|
|
||||||
- name: Configure Age
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
AGE_FORGE_SSH_KEY: ${{ secrets.AGE_FORGE_SSH_KEY }}
|
|
||||||
run: Scripts/resolve-age-identity.sh >> "$GITHUB_ENV"
|
|
||||||
|
|
||||||
- name: Decrypt Release Secrets
|
|
||||||
uses: ./.forgejo/actions/decrypt-release-secrets
|
|
||||||
|
|
||||||
- name: Validate App Store Credentials
|
|
||||||
shell: bash
|
|
||||||
run: Scripts/ci/check-release-config.sh app-store
|
|
||||||
|
|
||||||
- name: Download Staged Apple Artifacts
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
BUILD_NUMBER: ${{ inputs.build_number }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
nix develop .#ci -c Scripts/ci/google-wif-auth.sh
|
|
||||||
mkdir -p "dist/builds/${BUILD_NUMBER}/apple"
|
|
||||||
nix develop .#ci -c gcloud storage rsync --recursive "gs://${BURROW_RELEASE_GCS_BUCKET}/builds/${BUILD_NUMBER}/apple" "dist/builds/${BUILD_NUMBER}/apple"
|
|
||||||
find "dist/builds/${BUILD_NUMBER}/apple" -type f -print | sort
|
|
||||||
|
|
||||||
- name: Sync Apple Provisioning Profiles
|
|
||||||
shell: bash
|
|
||||||
run: nix develop .#ci -c Scripts/ci/sync-apple-provisioning-profiles.sh all
|
|
||||||
|
|
||||||
- name: Sign Apple Artifacts With KMS
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
BUILD_NUMBER: ${{ inputs.build_number }}
|
|
||||||
SPARKLE_CHANNEL_INPUT: ${{ inputs.sparkle_channel }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
channel="${SPARKLE_CHANNEL_INPUT:-}"
|
|
||||||
if [[ -z "$channel" ]]; then
|
|
||||||
channel="build-${BUILD_NUMBER}"
|
|
||||||
fi
|
|
||||||
SPARKLE_CHANNEL="$channel" nix develop .#ci -c Scripts/apple/sign-release-artifacts-kms.sh all
|
|
||||||
|
|
||||||
- name: Upload Signed Apple Artifacts
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
BUILD_NUMBER: ${{ inputs.build_number }}
|
|
||||||
run: nix develop .#ci -c Scripts/ci/upload-release-storage.sh
|
|
||||||
|
|
||||||
upload-app-store:
|
|
||||||
name: Upload (App Store Connect)
|
|
||||||
needs: sign-apple-kms
|
|
||||||
if: ${{ inputs.upload_app_store == 'true' }}
|
|
||||||
runs-on: namespace-profile-macos-large
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
with:
|
|
||||||
token: ${{ github.token }}
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Ensure Nix
|
|
||||||
shell: bash
|
|
||||||
run: bash Scripts/ci/ensure-nix.sh
|
|
||||||
|
|
||||||
- name: Configure Age
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
AGE_FORGE_SSH_KEY: ${{ secrets.AGE_FORGE_SSH_KEY }}
|
|
||||||
run: Scripts/resolve-age-identity.sh >> "$GITHUB_ENV"
|
|
||||||
|
|
||||||
- name: Decrypt Release Secrets
|
|
||||||
uses: ./.forgejo/actions/decrypt-release-secrets
|
|
||||||
|
|
||||||
- name: Validate App Store Credentials
|
|
||||||
shell: bash
|
|
||||||
run: Scripts/ci/check-release-config.sh app-store
|
|
||||||
|
|
||||||
- name: Download Apple Artifacts From GCS
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
BUILD_NUMBER: ${{ inputs.build_number }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
nix develop .#ci -c Scripts/ci/google-wif-auth.sh
|
|
||||||
mkdir -p publish/apple
|
|
||||||
nix develop .#ci -c gcloud storage rsync --recursive "gs://${BURROW_RELEASE_GCS_BUCKET}/builds/${BUILD_NUMBER}/apple" publish/apple
|
|
||||||
find publish/apple -type f -print | sort
|
|
||||||
|
|
||||||
- name: Upload Apple Packages
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
Scripts/ci/check-release-config.sh app-store
|
|
||||||
key_dir="${RUNNER_TEMP:-/tmp}/burrow-asc"
|
|
||||||
altool_key_dir="${HOME}/.appstoreconnect/private_keys"
|
|
||||||
mkdir -p "$key_dir" "$altool_key_dir"
|
|
||||||
key_path="$key_dir/AuthKey_${ASC_API_KEY_ID}.p8"
|
|
||||||
if [[ -n "${ASC_API_KEY_PATH:-}" && -f "${ASC_API_KEY_PATH:-}" ]]; then
|
|
||||||
cp "$ASC_API_KEY_PATH" "$key_path"
|
|
||||||
else
|
|
||||||
printf '%s' "$ASC_API_KEY_BASE64" | base64 --decode > "$key_path"
|
|
||||||
fi
|
|
||||||
cp "$key_path" "$altool_key_dir/AuthKey_${ASC_API_KEY_ID}.p8"
|
|
||||||
chmod 600 "$key_path" "$altool_key_dir/AuthKey_${ASC_API_KEY_ID}.p8"
|
|
||||||
shopt -s nullglob
|
|
||||||
artifacts=()
|
|
||||||
for artifact in publish/apple/*.ipa publish/apple/*.pkg; do
|
|
||||||
[[ "$artifact" == *.unsigned.ipa ]] && continue
|
|
||||||
artifacts+=("$artifact")
|
|
||||||
done
|
|
||||||
if (( ${#artifacts[@]} == 0 )); then
|
|
||||||
echo "::error ::No Apple upload artifacts found for build ${{ inputs.build_number }}."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
for artifact in "${artifacts[@]}"; do
|
|
||||||
upload_type="ios"
|
|
||||||
if [[ "$artifact" == *.pkg ]]; then
|
|
||||||
upload_type="macos"
|
|
||||||
fi
|
|
||||||
upload_log="${RUNNER_TEMP:-/tmp}/burrow-altool-${upload_type}-$(basename "$artifact").log"
|
|
||||||
set +e
|
|
||||||
xcrun altool --upload-app \
|
|
||||||
--type "$upload_type" \
|
|
||||||
--file "$artifact" \
|
|
||||||
--apiKey "$ASC_API_KEY_ID" \
|
|
||||||
--apiIssuer "$ASC_API_ISSUER_ID" 2>&1 | tee "$upload_log"
|
|
||||||
altool_status=${PIPESTATUS[0]}
|
|
||||||
set -e
|
|
||||||
if (( altool_status != 0 )) || grep -Eq 'UPLOAD FAILED|Validation failed|ERROR:' "$upload_log"; then
|
|
||||||
echo "::error ::altool reported upload validation failure for $artifact" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
release-ios-testflight:
|
|
||||||
name: Release (TestFlight iOS Testers)
|
|
||||||
needs: upload-app-store
|
|
||||||
if: ${{ inputs.upload_app_store == 'true' }}
|
|
||||||
runs-on: namespace-profile-linux-testflight
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
with:
|
|
||||||
token: ${{ github.token }}
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Ensure Nix
|
|
||||||
shell: bash
|
|
||||||
run: bash Scripts/ci/ensure-nix.sh
|
|
||||||
|
|
||||||
- name: Configure Age
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
AGE_FORGE_SSH_KEY: ${{ secrets.AGE_FORGE_SSH_KEY }}
|
|
||||||
run: Scripts/resolve-age-identity.sh >> "$GITHUB_ENV"
|
|
||||||
|
|
||||||
- name: Decrypt Release Secrets
|
|
||||||
uses: ./.forgejo/actions/decrypt-release-secrets
|
|
||||||
|
|
||||||
- name: Validate App Store Credentials
|
|
||||||
shell: bash
|
|
||||||
run: Scripts/ci/check-release-config.sh app-store
|
|
||||||
|
|
||||||
- name: Distribute iOS Build To TestFlight
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
BUILD_NUMBER: ${{ inputs.build_number }}
|
|
||||||
TESTFLIGHT_DISTRIBUTE_EXTERNAL: ${{ inputs.testflight_distribute_external || 'false' }}
|
|
||||||
TESTFLIGHT_GROUPS: ${{ inputs.testflight_groups || '' }}
|
|
||||||
IOS_USES_NON_EXEMPT_ENCRYPTION: ${{ inputs.ios_uses_non_exempt_encryption || 'false' }}
|
|
||||||
run: Scripts/ci/distribute-testflight.sh
|
|
||||||
|
|
||||||
distribute-ios-testflight:
|
|
||||||
name: Distribute (TestFlight iOS Testers)
|
|
||||||
if: ${{ inputs.upload_app_store != 'true' && inputs.distribute_testflight == 'true' }}
|
|
||||||
runs-on: namespace-profile-linux-testflight
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
with:
|
|
||||||
token: ${{ github.token }}
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Ensure Nix
|
|
||||||
shell: bash
|
|
||||||
run: bash Scripts/ci/ensure-nix.sh
|
|
||||||
|
|
||||||
- name: Configure Age
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
AGE_FORGE_SSH_KEY: ${{ secrets.AGE_FORGE_SSH_KEY }}
|
|
||||||
run: Scripts/resolve-age-identity.sh >> "$GITHUB_ENV"
|
|
||||||
|
|
||||||
- name: Decrypt Release Secrets
|
|
||||||
uses: ./.forgejo/actions/decrypt-release-secrets
|
|
||||||
|
|
||||||
- name: Validate App Store Credentials
|
|
||||||
shell: bash
|
|
||||||
run: Scripts/ci/check-release-config.sh app-store
|
|
||||||
|
|
||||||
- name: Distribute iOS Build To TestFlight
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
BUILD_NUMBER: ${{ inputs.build_number }}
|
|
||||||
TESTFLIGHT_DISTRIBUTE_EXTERNAL: ${{ inputs.testflight_distribute_external || 'false' }}
|
|
||||||
TESTFLIGHT_GROUPS: ${{ inputs.testflight_groups || '' }}
|
|
||||||
IOS_USES_NON_EXEMPT_ENCRYPTION: ${{ inputs.ios_uses_non_exempt_encryption || 'false' }}
|
|
||||||
run: Scripts/ci/distribute-testflight.sh
|
|
||||||
|
|
||||||
upload-sparkle:
|
|
||||||
name: Upload (Sparkle)
|
|
||||||
needs: sign-apple-kms
|
|
||||||
if: ${{ inputs.upload_sparkle == 'true' }}
|
|
||||||
runs-on: namespace-profile-linux-medium
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
with:
|
|
||||||
token: ${{ github.token }}
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Resolve Sparkle Channel
|
|
||||||
id: channel
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
BUILD_NUMBER: ${{ inputs.build_number }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
channel="${{ inputs.sparkle_channel }}"
|
|
||||||
if [[ -z "$channel" ]]; then
|
|
||||||
channel="build-${BUILD_NUMBER}"
|
|
||||||
fi
|
|
||||||
echo "channel=$channel" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
- name: Ensure Nix
|
|
||||||
shell: bash
|
|
||||||
run: bash Scripts/ci/ensure-nix.sh
|
|
||||||
|
|
||||||
- name: Publish Sparkle Channel
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
BUILD_NUMBER: ${{ inputs.build_number }}
|
|
||||||
CHANNEL: ${{ steps.channel.outputs.channel }}
|
|
||||||
SPARKLE_POINT_MAIN: ${{ inputs.sparkle_point_main }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
nix develop .#ci -c Scripts/ci/google-wif-auth.sh
|
|
||||||
mkdir -p "publish/sparkle/${CHANNEL}"
|
|
||||||
nix develop .#ci -c gcloud storage rsync --recursive "gs://${BURROW_RELEASE_GCS_BUCKET}/builds/${BUILD_NUMBER}/sparkle/${CHANNEL}" "publish/sparkle/${CHANNEL}" || true
|
|
||||||
if [[ ! -f "publish/sparkle/${CHANNEL}/appcast.xml" ]]; then
|
|
||||||
echo "::warning ::No Sparkle appcast staged for build ${BUILD_NUMBER}; skipping Sparkle publish."
|
|
||||||
find "publish/sparkle/${CHANNEL}" -maxdepth 2 -type f -print || true
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
nix develop .#ci -c gcloud storage rsync --recursive "publish/sparkle/${CHANNEL}" "gs://${BURROW_RELEASE_GCS_BUCKET}/sparkle/${CHANNEL}"
|
|
||||||
if [[ "$SPARKLE_POINT_MAIN" == "true" ]]; then
|
|
||||||
printf '%s\n' "$CHANNEL" > main-channel.txt
|
|
||||||
nix develop .#ci -c gcloud storage cp main-channel.txt "gs://${BURROW_RELEASE_GCS_BUCKET}/sparkle/main-channel.txt"
|
|
||||||
nix develop .#ci -c gcloud storage cp "publish/sparkle/${CHANNEL}/appcast.xml" "gs://${BURROW_RELEASE_GCS_BUCKET}/sparkle/appcast.xml"
|
|
||||||
nix develop .#ci -c gcloud storage rsync --recursive "publish/sparkle/${CHANNEL}" "gs://${BURROW_RELEASE_GCS_BUCKET}/sparkle/default"
|
|
||||||
fi
|
|
||||||
|
|
||||||
upload-microsoft-store:
|
|
||||||
name: Upload (Microsoft Store Beta)
|
|
||||||
if: ${{ inputs.upload_microsoft_store == 'true' }}
|
|
||||||
runs-on: namespace-profile-windows-large
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
with:
|
|
||||||
token: ${{ github.token }}
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Validate Microsoft Store Credentials
|
|
||||||
shell: pwsh
|
|
||||||
env:
|
|
||||||
MICROSOFT_TENANT_ID: ${{ secrets.MICROSOFT_TENANT_ID }}
|
|
||||||
MICROSOFT_CLIENT_ID: ${{ secrets.MICROSOFT_CLIENT_ID }}
|
|
||||||
MICROSOFT_CLIENT_SECRET: ${{ secrets.MICROSOFT_CLIENT_SECRET }}
|
|
||||||
run: |
|
|
||||||
foreach ($name in "MICROSOFT_TENANT_ID","MICROSOFT_CLIENT_ID","MICROSOFT_CLIENT_SECRET") {
|
|
||||||
if ([string]::IsNullOrWhiteSpace([Environment]::GetEnvironmentVariable($name))) {
|
|
||||||
throw "missing required environment variable: $name"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- name: Stop Until Store Package Exists
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
Write-Host "::warning ::Burrow only builds a Windows Rust stub today; Microsoft Store package upload is wired for credentials but waits on MSIX packaging."
|
|
||||||
|
|
@ -1,92 +0,0 @@
|
||||||
name: "Release: If Needed"
|
|
||||||
run-name: "Release: If Needed (${{ github.ref_name }})"
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
schedule:
|
|
||||||
- cron: "*/30 * * * *"
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
upload_app_store:
|
|
||||||
description: Trigger downstream App Store Connect upload workflow
|
|
||||||
required: false
|
|
||||||
default: "true"
|
|
||||||
upload_sparkle:
|
|
||||||
description: Trigger downstream Sparkle publish workflow
|
|
||||||
required: false
|
|
||||||
default: "true"
|
|
||||||
upload_microsoft_store:
|
|
||||||
description: Trigger downstream Microsoft Store beta upload workflow
|
|
||||||
required: false
|
|
||||||
default: "false"
|
|
||||||
sparkle_point_main:
|
|
||||||
description: Update Sparkle main channel pointers
|
|
||||||
required: false
|
|
||||||
default: "true"
|
|
||||||
testflight_distribute_external:
|
|
||||||
description: Distribute to external TestFlight groups
|
|
||||||
required: false
|
|
||||||
default: "false"
|
|
||||||
testflight_groups:
|
|
||||||
description: Optional comma-separated TestFlight groups for external distribution
|
|
||||||
required: false
|
|
||||||
default: ""
|
|
||||||
ios_uses_non_exempt_encryption:
|
|
||||||
description: Set true only when the iOS build uses non-exempt encryption
|
|
||||||
required: false
|
|
||||||
default: "false"
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
actions: write
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: burrow-release-if-needed-main
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ github.token }}
|
|
||||||
BURROW_VERSION_REQUIRE_REMOTE: "1"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
check:
|
|
||||||
name: Check (Release Needed)
|
|
||||||
runs-on: namespace-profile-linux-medium
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
with:
|
|
||||||
token: ${{ github.token }}
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Fetch Build Tags
|
|
||||||
shell: bash
|
|
||||||
run: git fetch --force --prune origin "+refs/tags/builds/*:refs/tags/builds/*"
|
|
||||||
|
|
||||||
- name: Dispatch Release Build
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
UPLOAD_APP_STORE: ${{ github.event.inputs.upload_app_store || 'true' }}
|
|
||||||
UPLOAD_SPARKLE: ${{ github.event.inputs.upload_sparkle || 'true' }}
|
|
||||||
UPLOAD_MICROSOFT_STORE: ${{ github.event.inputs.upload_microsoft_store || 'false' }}
|
|
||||||
SPARKLE_POINT_MAIN: ${{ github.event.inputs.sparkle_point_main || 'true' }}
|
|
||||||
TESTFLIGHT_DISTRIBUTE_EXTERNAL: ${{ github.event.inputs.testflight_distribute_external || 'false' }}
|
|
||||||
TESTFLIGHT_GROUPS: ${{ github.event.inputs.testflight_groups || '' }}
|
|
||||||
IOS_USES_NON_EXEMPT_ENCRYPTION: ${{ github.event.inputs.ios_uses_non_exempt_encryption || 'false' }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
status="$(Scripts/version.sh status)"
|
|
||||||
if [[ "$status" == "clean" ]]; then
|
|
||||||
echo "No unreleased changes."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
inputs="$(python3 -c 'import json, os; print(json.dumps({"upload_app_store":os.environ["UPLOAD_APP_STORE"],"upload_sparkle":os.environ["UPLOAD_SPARKLE"],"upload_microsoft_store":os.environ["UPLOAD_MICROSOFT_STORE"],"sparkle_point_main":os.environ["SPARKLE_POINT_MAIN"],"testflight_distribute_external":os.environ["TESTFLIGHT_DISTRIBUTE_EXTERNAL"],"testflight_groups":os.environ["TESTFLIGHT_GROUPS"],"ios_uses_non_exempt_encryption":os.environ["IOS_USES_NON_EXEMPT_ENCRYPTION"]}))')"
|
|
||||||
curl -fsS \
|
|
||||||
-X POST \
|
|
||||||
-H "Authorization: token ${GITHUB_TOKEN}" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d "{\"ref\":\"main\",\"inputs\":${inputs}}" \
|
|
||||||
"${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/actions/workflows/build-release.yml/dispatches"
|
|
||||||
echo "Dispatched build-release.yml (status=${status})."
|
|
||||||
|
|
@ -1,77 +0,0 @@
|
||||||
name: Release
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- "v*"
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: false
|
|
||||||
|
|
||||||
env:
|
|
||||||
BURROW_NIX_CACHE_URL: ${{ vars.BURROW_NIX_CACHE_URL || 'https://nix.burrow.net/burrow' }}
|
|
||||||
BURROW_NIX_CACHE_PUBLIC_KEY: ${{ vars.BURROW_NIX_CACHE_PUBLIC_KEY }}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
release:
|
|
||||||
name: Release Build
|
|
||||||
runs-on: namespace-profile-linux-medium
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
with:
|
|
||||||
token: ${{ github.token }}
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Bootstrap Nix
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
chmod +x Scripts/ci/ensure-nix.sh
|
|
||||||
Scripts/ci/ensure-nix.sh
|
|
||||||
|
|
||||||
- name: Build release artifacts
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
RELEASE_REF: ${{ github.ref_name }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
ref="${RELEASE_REF:-manual-${GITHUB_SHA::7}}"
|
|
||||||
export RELEASE_REF="${ref}"
|
|
||||||
chmod +x Scripts/ci/build-release-artifacts.sh
|
|
||||||
nix develop .#ci -c Scripts/ci/build-release-artifacts.sh
|
|
||||||
|
|
||||||
- name: Flatten release assets
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
RELEASE_REF: ${{ github.ref_name }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
ref="${RELEASE_REF:-manual-${GITHUB_SHA::7}}"
|
|
||||||
mkdir -p dist/release-assets
|
|
||||||
find "dist/builds/${ref}" -type f \( -name '*.tar.gz' -o -name '*.zip' -o -name '*.sha256' -o -name 'README.txt' \) -exec cp {} dist/release-assets/ \;
|
|
||||||
rm -rf dist/builds
|
|
||||||
cp dist/release-assets/* dist/
|
|
||||||
find dist -maxdepth 1 -type f -print | sort
|
|
||||||
|
|
||||||
- name: Upload release artifacts
|
|
||||||
uses: https://code.forgejo.org/actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: burrow-release-${{ github.ref_name }}
|
|
||||||
path: dist/*
|
|
||||||
if-no-files-found: error
|
|
||||||
|
|
||||||
- name: Publish Forgejo release
|
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
RELEASE_TAG: ${{ github.ref_name }}
|
|
||||||
API_URL: ${{ github.api_url }}
|
|
||||||
REPOSITORY: ${{ github.repository }}
|
|
||||||
TOKEN: ${{ github.token }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
chmod +x Scripts/ci/publish-forgejo-release.sh
|
|
||||||
nix develop .#ci -c Scripts/ci/publish-forgejo-release.sh
|
|
||||||
5
.github/CODEOWNERS
vendored
|
|
@ -1,4 +1 @@
|
||||||
* @conradev @malted @JettChenT @jdogcoder
|
* @conradev
|
||||||
burrow/ @conradev @malted @JettChenT @jdogcoder @Muirrum
|
|
||||||
tun/ @conradev @malted @JettChenT @jdogcoder @Muirrum
|
|
||||||
burrow-gtk/ @conradev @malted @JettChenT @jdogcoder @davnotdev
|
|
||||||
|
|
|
||||||
8
.github/actions/archive/action.yml
vendored
|
|
@ -26,18 +26,18 @@ runs:
|
||||||
run: |
|
run: |
|
||||||
echo "${{ inputs.app-store-key }}" > AuthKey_${{ inputs.app-store-key-id }}.p8
|
echo "${{ inputs.app-store-key }}" > AuthKey_${{ inputs.app-store-key-id }}.p8
|
||||||
|
|
||||||
xcodebuild clean archive \
|
xcodebuild archive \
|
||||||
-allowProvisioningUpdates \
|
-allowProvisioningUpdates \
|
||||||
-allowProvisioningDeviceRegistration \
|
-allowProvisioningDeviceRegistration \
|
||||||
-skipPackagePluginValidation \
|
|
||||||
-skipMacroValidation \
|
|
||||||
-onlyUsePackageVersionsFromResolvedFile \
|
|
||||||
-authenticationKeyID ${{ inputs.app-store-key-id }} \
|
-authenticationKeyID ${{ inputs.app-store-key-id }} \
|
||||||
-authenticationKeyIssuerID ${{ inputs.app-store-key-issuer-id }} \
|
-authenticationKeyIssuerID ${{ inputs.app-store-key-issuer-id }} \
|
||||||
-authenticationKeyPath "${PWD}/AuthKey_${{ inputs.app-store-key-id }}.p8" \
|
-authenticationKeyPath "${PWD}/AuthKey_${{ inputs.app-store-key-id }}.p8" \
|
||||||
|
-onlyUsePackageVersionsFromResolvedFile \
|
||||||
-scheme '${{ inputs.scheme }}' \
|
-scheme '${{ inputs.scheme }}' \
|
||||||
-destination '${{ inputs.destination }}' \
|
-destination '${{ inputs.destination }}' \
|
||||||
-archivePath '${{ inputs.archive-path }}' \
|
-archivePath '${{ inputs.archive-path }}' \
|
||||||
-resultBundlePath BuildResults.xcresult
|
-resultBundlePath BuildResults.xcresult
|
||||||
|
|
||||||
|
./Tools/xcresulttool-github BuildResults.xcresult
|
||||||
|
|
||||||
rm -rf AuthKey_${{ inputs.app-store-key-id }}.p8
|
rm -rf AuthKey_${{ inputs.app-store-key-id }}.p8
|
||||||
|
|
|
||||||
24
.github/actions/build-for-testing/action.yml
vendored
|
|
@ -18,36 +18,18 @@ inputs:
|
||||||
runs:
|
runs:
|
||||||
using: composite
|
using: composite
|
||||||
steps:
|
steps:
|
||||||
- name: Xcode Cache
|
- shell: bash
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
Apple/PackageCache
|
|
||||||
Apple/SourcePackages
|
|
||||||
Apple/DerivedData
|
|
||||||
key: ${{ runner.os }}-${{ inputs.scheme }}-${{ hashFiles('**/Package.resolved') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-${{ inputs.scheme }}-${{ hashFiles('**/Package.resolved') }}
|
|
||||||
${{ runner.os }}-${{ inputs.scheme }}-
|
|
||||||
${{ runner.os }}-
|
|
||||||
- name: Build
|
|
||||||
shell: bash
|
|
||||||
working-directory: Apple
|
working-directory: Apple
|
||||||
run: |
|
run: |
|
||||||
echo "${{ inputs.app-store-key }}" > AuthKey_${{ inputs.app-store-key-id }}.p8
|
echo "${{ inputs.app-store-key }}" > AuthKey_${{ inputs.app-store-key-id }}.p8
|
||||||
|
|
||||||
xcodebuild build-for-testing \
|
xcodebuild clean build-for-testing \
|
||||||
-allowProvisioningUpdates \
|
-allowProvisioningUpdates \
|
||||||
-allowProvisioningDeviceRegistration \
|
-allowProvisioningDeviceRegistration \
|
||||||
-skipPackagePluginValidation \
|
|
||||||
-skipMacroValidation \
|
|
||||||
-onlyUsePackageVersionsFromResolvedFile \
|
|
||||||
-authenticationKeyID ${{ inputs.app-store-key-id }} \
|
-authenticationKeyID ${{ inputs.app-store-key-id }} \
|
||||||
-authenticationKeyIssuerID ${{ inputs.app-store-key-issuer-id }} \
|
-authenticationKeyIssuerID ${{ inputs.app-store-key-issuer-id }} \
|
||||||
-authenticationKeyPath "${PWD}/AuthKey_${{ inputs.app-store-key-id }}.p8" \
|
-authenticationKeyPath "${PWD}/AuthKey_${{ inputs.app-store-key-id }}.p8" \
|
||||||
-clonedSourcePackagesDirPath SourcePackages \
|
-onlyUsePackageVersionsFromResolvedFile \
|
||||||
-packageCachePath $PWD/PackageCache \
|
|
||||||
-derivedDataPath $PWD/DerivedData \
|
|
||||||
-scheme '${{ inputs.scheme }}' \
|
-scheme '${{ inputs.scheme }}' \
|
||||||
-destination '${{ inputs.destination }}' \
|
-destination '${{ inputs.destination }}' \
|
||||||
-resultBundlePath BuildResults.xcresult
|
-resultBundlePath BuildResults.xcresult
|
||||||
|
|
|
||||||
30
.github/actions/download-profiles/action.yml
vendored
|
|
@ -1,30 +0,0 @@
|
||||||
name: Download Provisioning Profiles
|
|
||||||
inputs:
|
|
||||||
app-store-key:
|
|
||||||
description: App Store key in PEM PKCS#8 format
|
|
||||||
required: true
|
|
||||||
app-store-key-id:
|
|
||||||
description: App Store key ID
|
|
||||||
required: true
|
|
||||||
app-store-key-issuer-id:
|
|
||||||
description: App Store key issuer ID
|
|
||||||
required: true
|
|
||||||
runs:
|
|
||||||
using: composite
|
|
||||||
steps:
|
|
||||||
- shell: bash
|
|
||||||
env:
|
|
||||||
FASTLANE_OPT_OUT_USAGE: 'YES'
|
|
||||||
run: |
|
|
||||||
APP_STORE_KEY=$(echo "${{ inputs.app-store-key }}" | jq -sR .)
|
|
||||||
cat << EOF > api-key.json
|
|
||||||
{
|
|
||||||
"key_id": "${{ inputs.app-store-key-id }}",
|
|
||||||
"issuer_id": "${{ inputs.app-store-key-issuer-id }}",
|
|
||||||
"key": $APP_STORE_KEY
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
|
|
||||||
fastlane sigh download_all --api_key_path api-key.json
|
|
||||||
|
|
||||||
rm -rf api-key.json
|
|
||||||
18
.github/actions/export/action.yml
vendored
|
|
@ -1,4 +1,4 @@
|
||||||
name: Export
|
name: Notarize
|
||||||
inputs:
|
inputs:
|
||||||
app-store-key:
|
app-store-key:
|
||||||
description: App Store key in PEM PKCS#8 format
|
description: App Store key in PEM PKCS#8 format
|
||||||
|
|
@ -12,8 +12,11 @@ inputs:
|
||||||
archive-path:
|
archive-path:
|
||||||
description: Xcode archive path
|
description: Xcode archive path
|
||||||
required: true
|
required: true
|
||||||
export-options:
|
destination:
|
||||||
description: The export options in JSON format
|
description: The Xcode export destination. This can either be "export" or "upload"
|
||||||
|
required: true
|
||||||
|
method:
|
||||||
|
description: The Xcode export method. This can be one of app-store, validation, ad-hoc, package, enterprise, development, developer-id, or mac-application.
|
||||||
required: true
|
required: true
|
||||||
export-path:
|
export-path:
|
||||||
description: The path to export the archive to
|
description: The path to export the archive to
|
||||||
|
|
@ -21,20 +24,19 @@ inputs:
|
||||||
runs:
|
runs:
|
||||||
using: composite
|
using: composite
|
||||||
steps:
|
steps:
|
||||||
- shell: bash
|
- id: notarize
|
||||||
|
shell: bash
|
||||||
working-directory: Apple
|
working-directory: Apple
|
||||||
run: |
|
run: |
|
||||||
echo "${{ inputs.app-store-key }}" > AuthKey_${{ inputs.app-store-key-id }}.p8
|
echo "${{ inputs.app-store-key }}" > AuthKey_${{ inputs.app-store-key-id }}.p8
|
||||||
|
|
||||||
echo '${{ inputs.export-options }}' | plutil -convert xml1 -o ExportOptions.plist -
|
echo '{"destination":"${{ inputs.destination }}","method":"${{ inputs.method }}"}' \
|
||||||
|
| plutil -convert xml1 -o ExportOptions.plist -
|
||||||
|
|
||||||
xcodebuild \
|
xcodebuild \
|
||||||
-exportArchive \
|
-exportArchive \
|
||||||
-allowProvisioningUpdates \
|
-allowProvisioningUpdates \
|
||||||
-allowProvisioningDeviceRegistration \
|
-allowProvisioningDeviceRegistration \
|
||||||
-skipPackagePluginValidation \
|
|
||||||
-skipMacroValidation \
|
|
||||||
-onlyUsePackageVersionsFromResolvedFile \
|
|
||||||
-authenticationKeyID ${{ inputs.app-store-key-id }} \
|
-authenticationKeyID ${{ inputs.app-store-key-id }} \
|
||||||
-authenticationKeyIssuerID ${{ inputs.app-store-key-issuer-id }} \
|
-authenticationKeyIssuerID ${{ inputs.app-store-key-issuer-id }} \
|
||||||
-authenticationKeyPath "${PWD}/AuthKey_${{ inputs.app-store-key-id }}.p8" \
|
-authenticationKeyPath "${PWD}/AuthKey_${{ inputs.app-store-key-id }}.p8" \
|
||||||
|
|
|
||||||
25
.github/actions/notarize/action.yml
vendored
|
|
@ -1,25 +0,0 @@
|
||||||
name: Notarize
|
|
||||||
inputs:
|
|
||||||
app-store-key:
|
|
||||||
description: App Store key in PEM PKCS#8 format
|
|
||||||
required: true
|
|
||||||
app-store-key-id:
|
|
||||||
description: App Store key ID
|
|
||||||
required: true
|
|
||||||
app-store-key-issuer-id:
|
|
||||||
description: App Store key issuer ID
|
|
||||||
required: true
|
|
||||||
runs:
|
|
||||||
using: composite
|
|
||||||
steps:
|
|
||||||
- id: notarize
|
|
||||||
shell: bash
|
|
||||||
working-directory: Apple
|
|
||||||
run: |
|
|
||||||
echo "${{ inputs.app-store-key }}" > AuthKey_${{ inputs.app-store-key-id }}.p8
|
|
||||||
|
|
||||||
ditto -c -k --keepParent Release/Burrow.app Upload.zip
|
|
||||||
xcrun notarytool submit --wait --issuer ${{ inputs.app-store-key-issuer-id }} --key-id ${{ inputs.app-store-key-id }} --key "${PWD}/AuthKey_${{ inputs.app-store-key-id }}.p8" Upload.zip
|
|
||||||
xcrun stapler staple Release/Burrow.app
|
|
||||||
|
|
||||||
rm -rf AuthKey_${{ inputs.app-store-key-id }}.p8 Release
|
|
||||||
|
|
@ -18,6 +18,9 @@ inputs:
|
||||||
runs:
|
runs:
|
||||||
using: composite
|
using: composite
|
||||||
steps:
|
steps:
|
||||||
|
- shell: bash
|
||||||
|
id: vars
|
||||||
|
run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||||
- shell: bash
|
- shell: bash
|
||||||
working-directory: Apple
|
working-directory: Apple
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -25,10 +28,10 @@ runs:
|
||||||
-scheme '${{ inputs.scheme }}' \
|
-scheme '${{ inputs.scheme }}' \
|
||||||
-destination '${{ inputs.destination }}' \
|
-destination '${{ inputs.destination }}' \
|
||||||
${{ inputs.test-plan && '-testPlan ' }}${{ inputs.test-plan }} \
|
${{ inputs.test-plan && '-testPlan ' }}${{ inputs.test-plan }} \
|
||||||
-resultBundlePath "${{ inputs.artifact-prefix }}.xcresult"
|
-resultBundlePath "${{ inputs.artifact-prefix }}-${{ steps.vars.outputs.sha_short }}.xcresult"
|
||||||
- uses: kishikawakatsumi/xcresulttool@v1
|
- uses: kishikawakatsumi/xcresulttool@v1
|
||||||
if: always()
|
if: always()
|
||||||
with:
|
with:
|
||||||
path: Apple/${{ inputs.artifact-prefix }}.xcresult
|
path: Apple/${{ inputs.artifact-prefix }}-${{ steps.vars.outputs.sha_short }}.xcresult
|
||||||
title: ${{ inputs.check-name }}
|
title: ${{ inputs.check-name }}
|
||||||
show-passed-tests: false
|
show-passed-tests: false
|
||||||
|
|
|
||||||
29
.github/workflows/build-appimage.yml
vendored
|
|
@ -1,29 +0,0 @@
|
||||||
name: Build AppImage
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- "*"
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
jobs:
|
|
||||||
appimage:
|
|
||||||
name: Build AppImage
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
container: docker
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Build AppImage
|
|
||||||
run: |
|
|
||||||
docker build -t appimage-builder . -f burrow-gtk/build-aux/Dockerfile
|
|
||||||
docker create --name temp appimage-builder
|
|
||||||
docker cp temp:/app/burrow-gtk/build-appimage/Burrow-x86_64.AppImage .
|
|
||||||
docker rm temp
|
|
||||||
- uses: actions/upload-artifact@v4
|
|
||||||
name: Upload to GitHub
|
|
||||||
with:
|
|
||||||
name: AppImage
|
|
||||||
path: Burrow-x86_64.AppImage
|
|
||||||
38
.github/workflows/build-apple.yml
vendored
|
|
@ -1,4 +1,4 @@
|
||||||
name: Build Apple Apps
|
name: Apple Build
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|
@ -6,40 +6,28 @@ on:
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- "*"
|
- "*"
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Build App (${{ matrix.platform }})
|
name: Build App (${{ matrix.platform }})
|
||||||
runs-on: macos-14
|
runs-on: macos-12
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- scheme: App
|
- scheme: Burrow
|
||||||
destination: generic/platform=iOS
|
destination: generic/platform=iOS
|
||||||
platform: iOS
|
platform: iOS
|
||||||
sdk-name: iphoneos
|
sdk-name: iphoneos
|
||||||
rust-targets:
|
- scheme: Burrow
|
||||||
- aarch64-apple-ios
|
destination: platform=iOS Simulator,OS=16.2,name=iPhone 14 Pro
|
||||||
- scheme: App
|
|
||||||
destination: platform=iOS Simulator,OS=18.0,name=iPhone 15 Pro
|
|
||||||
platform: iOS Simulator
|
platform: iOS Simulator
|
||||||
sdk-name: iphonesimulator
|
sdk-name: iphonesimulator
|
||||||
rust-targets:
|
- scheme: Burrow
|
||||||
- aarch64-apple-ios-sim
|
|
||||||
- x86_64-apple-ios
|
|
||||||
- scheme: App
|
|
||||||
destination: platform=macOS
|
destination: platform=macOS
|
||||||
platform: macOS
|
platform: macOS
|
||||||
sdk-name: macos
|
sdk-name: macos
|
||||||
rust-targets:
|
|
||||||
- x86_64-apple-darwin
|
|
||||||
- aarch64-apple-darwin
|
|
||||||
env:
|
env:
|
||||||
DEVELOPER_DIR: /Applications/Xcode_16.0.app/Contents/Developer
|
DEVELOPER_DIR: /Applications/Xcode_14.2.app/Contents/Developer
|
||||||
PROTOC_PATH: /opt/homebrew/bin/protoc
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
@ -51,14 +39,6 @@ jobs:
|
||||||
with:
|
with:
|
||||||
certificate: ${{ secrets.DEVELOPER_CERT }}
|
certificate: ${{ secrets.DEVELOPER_CERT }}
|
||||||
password: ${{ secrets.DEVELOPER_CERT_PASSWORD }}
|
password: ${{ secrets.DEVELOPER_CERT_PASSWORD }}
|
||||||
- name: Install Rust
|
|
||||||
uses: dtolnay/rust-toolchain@stable
|
|
||||||
with:
|
|
||||||
toolchain: 1.85.0
|
|
||||||
targets: ${{ join(matrix.rust-targets, ', ') }}
|
|
||||||
- name: Install Protobuf
|
|
||||||
shell: bash
|
|
||||||
run: brew install protobuf
|
|
||||||
- name: Build
|
- name: Build
|
||||||
id: build
|
id: build
|
||||||
uses: ./.github/actions/build-for-testing
|
uses: ./.github/actions/build-for-testing
|
||||||
|
|
@ -68,7 +48,7 @@ jobs:
|
||||||
app-store-key: ${{ secrets.APPSTORE_KEY }}
|
app-store-key: ${{ secrets.APPSTORE_KEY }}
|
||||||
app-store-key-id: ${{ secrets.APPSTORE_KEY_ID }}
|
app-store-key-id: ${{ secrets.APPSTORE_KEY_ID }}
|
||||||
app-store-key-issuer-id: ${{ secrets.APPSTORE_KEY_ISSUER_ID }}
|
app-store-key-issuer-id: ${{ secrets.APPSTORE_KEY_ISSUER_ID }}
|
||||||
- name: Run Unit Tests
|
- name: Xcode Unit Test
|
||||||
if: ${{ matrix.xcode-unit-test != '' }}
|
if: ${{ matrix.xcode-unit-test != '' }}
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
uses: ./.github/actions/test-without-building
|
uses: ./.github/actions/test-without-building
|
||||||
|
|
@ -78,7 +58,7 @@ jobs:
|
||||||
test-plan: ${{ matrix.xcode-unit-test }}
|
test-plan: ${{ matrix.xcode-unit-test }}
|
||||||
artifact-prefix: unit-tests-${{ matrix.sdk-name }}
|
artifact-prefix: unit-tests-${{ matrix.sdk-name }}
|
||||||
check-name: Xcode Unit Tests (${{ matrix.platform }})
|
check-name: Xcode Unit Tests (${{ matrix.platform }})
|
||||||
- name: Run UI Tests
|
- name: Xcode UI Test
|
||||||
if: ${{ matrix.xcode-ui-test != '' }}
|
if: ${{ matrix.xcode-ui-test != '' }}
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
uses: ./.github/actions/test-without-building
|
uses: ./.github/actions/test-without-building
|
||||||
|
|
|
||||||
49
.github/workflows/build-docker.yml
vendored
|
|
@ -1,49 +0,0 @@
|
||||||
name: Build Docker
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- "*"
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
name: Build Docker Image
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
packages: write
|
|
||||||
contents: read
|
|
||||||
steps:
|
|
||||||
- name: Setup QEMU
|
|
||||||
uses: docker/setup-qemu-action@v2
|
|
||||||
with:
|
|
||||||
platforms: arm64
|
|
||||||
- name: Setup BuildKit
|
|
||||||
uses: docker/setup-buildx-action@v2
|
|
||||||
- name: Authenticate
|
|
||||||
uses: docker/login-action@v2
|
|
||||||
with:
|
|
||||||
registry: ghcr.io
|
|
||||||
username: ${{ github.repository_owner }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
- name: Extract Metadata
|
|
||||||
id: meta
|
|
||||||
uses: docker/metadata-action@v4
|
|
||||||
with:
|
|
||||||
images: ghcr.io/${{ github.repository }}
|
|
||||||
tags: |
|
|
||||||
type=sha
|
|
||||||
type=match,pattern=builds/(.*),group=1
|
|
||||||
type=raw,value=latest,enable={{is_default_branch}}
|
|
||||||
- name: Build and Push
|
|
||||||
uses: docker/build-push-action@v4
|
|
||||||
with:
|
|
||||||
platforms: ${{ github.event_name != 'pull_request' && 'linux/amd64,linux/arm64' || 'linux/amd64' }}
|
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
|
||||||
cache-from: type=gha
|
|
||||||
cache-to: type=gha,mode=max
|
|
||||||
16
.github/workflows/build-flatpak.yml
vendored
|
|
@ -1,16 +0,0 @@
|
||||||
on: workflow_dispatch
|
|
||||||
name: Build Flatpak
|
|
||||||
jobs:
|
|
||||||
flatpak:
|
|
||||||
name: Build Flatpak
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
container:
|
|
||||||
image: bilelmoussaoui/flatpak-github-actions:gnome-45
|
|
||||||
options: --privileged
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: flatpak/flatpak-github-actions/flatpak-builder@v6
|
|
||||||
with:
|
|
||||||
bundle: Burrow.flatpak
|
|
||||||
manifest-path: burrow-gtk/build-aux/com.hackclub.burrow.devel.json
|
|
||||||
cache-key: flatpak-builder-${{ github.sha }}
|
|
||||||
17
.github/workflows/build-rpm.yml
vendored
|
|
@ -1,17 +0,0 @@
|
||||||
on: workflow_dispatch
|
|
||||||
name: Build RPM
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
name: Build RPM
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: Swatinem/rust-cache@v2
|
|
||||||
- name: Install RPM
|
|
||||||
run: cargo install cargo-generate-rpm
|
|
||||||
- name: Build RPM
|
|
||||||
run: |
|
|
||||||
cargo build --release
|
|
||||||
strip -s target/release/burrow
|
|
||||||
- name: Build RPM
|
|
||||||
run: cargo generate-rpm -p burrow
|
|
||||||
52
.github/workflows/build-rust.yml
vendored
|
|
@ -1,4 +1,4 @@
|
||||||
name: Build Rust Crate
|
name: Rust Build
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
|
@ -6,9 +6,6 @@ on:
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- "*"
|
- "*"
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Build Crate (${{ matrix.platform }})
|
name: Build Crate (${{ matrix.platform }})
|
||||||
|
|
@ -20,38 +17,28 @@ jobs:
|
||||||
platform: Linux
|
platform: Linux
|
||||||
packages:
|
packages:
|
||||||
- gcc-aarch64-linux-gnu
|
- gcc-aarch64-linux-gnu
|
||||||
test-targets:
|
targets:
|
||||||
- x86_64-unknown-linux-gnu
|
- x86_64-unknown-linux-gnu
|
||||||
targets:
|
|
||||||
- aarch64-unknown-linux-gnu
|
- aarch64-unknown-linux-gnu
|
||||||
- os: macos-13
|
- os: macos-12
|
||||||
platform: macOS (Intel)
|
|
||||||
xcode: /Applications/Xcode_15.2.app
|
|
||||||
test-targets:
|
|
||||||
- x86_64-apple-darwin
|
|
||||||
targets:
|
|
||||||
- x86_64-apple-ios
|
|
||||||
- os: macos-14
|
|
||||||
platform: macOS
|
platform: macOS
|
||||||
xcode: /Applications/Xcode_16.0.app
|
|
||||||
test-targets:
|
|
||||||
- aarch64-apple-darwin
|
|
||||||
targets:
|
targets:
|
||||||
|
- x86_64-apple-darwin
|
||||||
|
- aarch64-apple-darwin
|
||||||
- aarch64-apple-ios
|
- aarch64-apple-ios
|
||||||
- aarch64-apple-ios-sim
|
- aarch64-apple-ios-sim
|
||||||
|
- x86_64-apple-ios
|
||||||
- os: windows-2022
|
- os: windows-2022
|
||||||
platform: Windows
|
platform: Windows
|
||||||
test-targets:
|
|
||||||
- x86_64-pc-windows-msvc
|
|
||||||
targets:
|
targets:
|
||||||
|
- x86_64-pc-windows-msvc
|
||||||
- aarch64-pc-windows-msvc
|
- aarch64-pc-windows-msvc
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
env:
|
env:
|
||||||
DEVELOPER_DIR: ${{ matrix.xcode }}/Contents/Developer
|
DEVELOPER_DIR: /Applications/Xcode_14.2.app/Contents/Developer
|
||||||
CARGO_INCREMENTAL: 0
|
CARGO_INCREMENTAL: 0
|
||||||
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
|
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
|
||||||
RUST_BACKTRACE: short
|
RUST_BACKTRACE: short
|
||||||
PROTOC_VERSION: 3.25.1
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
@ -61,28 +48,13 @@ jobs:
|
||||||
- name: Install Packages
|
- name: Install Packages
|
||||||
if: matrix.os == 'ubuntu-latest'
|
if: matrix.os == 'ubuntu-latest'
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: sudo apt-get install -y ${{ join(matrix.packages, ' ') }}
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y ${{ join(matrix.packages, ' ') }}
|
|
||||||
- name: Configure LLVM
|
|
||||||
if: matrix.os == 'windows-2022'
|
|
||||||
shell: bash
|
|
||||||
run: echo "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\Llvm\x64\bin" >> $GITHUB_PATH
|
|
||||||
- name: Install protoc
|
|
||||||
uses: taiki-e/install-action@v2
|
|
||||||
with:
|
|
||||||
tool: protoc@${{ env.PROTOC_VERSION }}
|
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: dtolnay/rust-toolchain@stable
|
uses: dtolnay/rust-toolchain@master
|
||||||
with:
|
with:
|
||||||
toolchain: 1.85.0
|
toolchain: stable
|
||||||
components: rustfmt
|
components: rustfmt
|
||||||
targets: ${{ join(matrix.targets, ', ') }}
|
targets: ${{ join(matrix.targets, ', ') }}
|
||||||
- name: Setup Rust Cache
|
|
||||||
uses: Swatinem/rust-cache@v2
|
|
||||||
- name: Build
|
- name: Build
|
||||||
shell: bash
|
shell: bash
|
||||||
run: cargo build --locked --verbose --workspace --all-features --target ${{ join(matrix.targets, ' --target ') }} --target ${{ join(matrix.test-targets, ' --target ') }}
|
run: cargo build --verbose --workspace --all-features --target ${{ join(matrix.targets, ' --target ') }}
|
||||||
- name: Test
|
|
||||||
shell: bash
|
|
||||||
run: cargo test --locked --verbose --workspace --all-features --target ${{ join(matrix.test-targets, ' --target ') }}
|
|
||||||
|
|
|
||||||
21
.github/workflows/lint-git.yml
vendored
|
|
@ -8,14 +8,13 @@ jobs:
|
||||||
name: Git Lint
|
name: Git Lint
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- uses: actions/checkout@v3
|
||||||
uses: actions/checkout@v4
|
with:
|
||||||
with:
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
fetch-depth: 0
|
||||||
fetch-depth: 0
|
- name: Install Gitlint
|
||||||
- name: Install
|
shell: bash
|
||||||
shell: bash
|
run: python -m pip install gitlint
|
||||||
run: python -m pip install gitlint
|
- name: Run Gitlint
|
||||||
- name: Lint
|
shell: bash
|
||||||
shell: bash
|
run: gitlint --commits "${{ github.event.pull_request.base.sha }}..HEAD"
|
||||||
run: gitlint --commits "${{ github.event.pull_request.base.sha }}..HEAD"
|
|
||||||
|
|
|
||||||
23
.github/workflows/lint-governance.yml
vendored
|
|
@ -1,23 +0,0 @@
|
||||||
name: Governance Lint
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- "*"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
governance:
|
|
||||||
name: BEP Metadata
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Validate BEP metadata
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
python3 Scripts/check-bep-metadata.py
|
|
||||||
9
.github/workflows/lint-swift.yml
vendored
|
|
@ -1,5 +1,8 @@
|
||||||
name: Swift Lint
|
name: Swift Lint
|
||||||
on:
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- "*"
|
- "*"
|
||||||
|
|
@ -11,6 +14,8 @@ jobs:
|
||||||
image: ghcr.io/realm/swiftlint:latest
|
image: ghcr.io/realm/swiftlint:latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
ssh-key: ${{ secrets.DEPLOY_KEY }}
|
||||||
- name: Lint
|
- name: Lint
|
||||||
run: swiftlint lint --strict --reporter github-actions-logging
|
run: swiftlint lint --reporter github-actions-logging
|
||||||
|
|
|
||||||
113
.github/workflows/release-apple.yml
vendored
|
|
@ -1,120 +1,65 @@
|
||||||
name: Release (Apple)
|
name: Build Apple Release
|
||||||
on:
|
on:
|
||||||
release:
|
release:
|
||||||
types:
|
types:
|
||||||
- created
|
- created
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Build ${{ matrix.platform }} Release
|
name: Build ${{ matrix.configuration['platform'] }} Release
|
||||||
runs-on: macos-14
|
runs-on: macos-12
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
configuration:
|
||||||
- platform: iOS
|
- scheme: App (iOS)
|
||||||
rust-targets:
|
destination: generic/platform=iOS
|
||||||
- aarch64-apple-ios
|
platform: iOS
|
||||||
- platform: macOS
|
method: ad-hoc
|
||||||
rust-targets:
|
artifact-file: Apple/Release/Burrow.ipa
|
||||||
- x86_64-apple-darwin
|
- scheme: App (macOS)
|
||||||
- aarch64-apple-darwin
|
destination: generic/platform=macOS
|
||||||
|
platform: macOS
|
||||||
|
method: mac-application
|
||||||
|
artifact-file: Burrow.app.txz
|
||||||
env:
|
env:
|
||||||
DEVELOPER_DIR: /Applications/Xcode_16.0.app/Contents/Developer
|
DEVELOPER_DIR: /Applications/Xcode_14.2.app/Contents/Developer
|
||||||
PROTOC_PATH: /opt/homebrew/bin/protoc
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
ssh-key: ${{ secrets.DEPLOY_KEY }}
|
||||||
|
submodules: recursive
|
||||||
- name: Import Certificate
|
- name: Import Certificate
|
||||||
uses: ./.github/actions/import-cert
|
uses: ./.github/actions/import-cert
|
||||||
with:
|
with:
|
||||||
certificate: ${{ secrets.DEVELOPER_CERT }}
|
certificate: ${{ secrets.DEVELOPER_CERT }}
|
||||||
password: ${{ secrets.DEVELOPER_CERT_PASSWORD }}
|
password: ${{ secrets.DEVELOPER_CERT_PASSWORD }}
|
||||||
- name: Download Provisioning Profiles
|
|
||||||
uses: ./.github/actions/download-profiles
|
|
||||||
with:
|
|
||||||
app-store-key: ${{ secrets.APPSTORE_KEY }}
|
|
||||||
app-store-key-id: ${{ secrets.APPSTORE_KEY_ID }}
|
|
||||||
app-store-key-issuer-id: ${{ secrets.APPSTORE_KEY_ISSUER_ID }}
|
|
||||||
- name: Install Provisioning Profiles
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles/
|
|
||||||
cp -f Apple/Profiles/* ~/Library/MobileDevice/Provisioning\ Profiles/
|
|
||||||
- name: Install Rust
|
|
||||||
uses: dtolnay/rust-toolchain@stable
|
|
||||||
with:
|
|
||||||
toolchain: 1.85.0
|
|
||||||
targets: ${{ join(matrix.rust-targets, ', ') }}
|
|
||||||
- name: Install Protobuf
|
|
||||||
shell: bash
|
|
||||||
run: brew install protobuf
|
|
||||||
- name: Configure Version
|
|
||||||
id: version
|
|
||||||
shell: bash
|
|
||||||
run: echo "BUILD_NUMBER=$(Tools/version.sh)" >> $GITHUB_OUTPUT
|
|
||||||
- name: Archive
|
- name: Archive
|
||||||
uses: ./.github/actions/archive
|
uses: ./.github/actions/archive
|
||||||
with:
|
with:
|
||||||
scheme: App
|
scheme: ${{ matrix.configuration['scheme'] }}
|
||||||
destination: generic/platform=${{ matrix.platform }}
|
destination: ${{ matrix.configuration['destination'] }}
|
||||||
app-store-key: ${{ secrets.APPSTORE_KEY }}
|
app-store-key: ${{ secrets.APPSTORE_KEY }}
|
||||||
app-store-key-id: ${{ secrets.APPSTORE_KEY_ID }}
|
app-store-key-id: ${{ secrets.APPSTORE_KEY_ID }}
|
||||||
app-store-key-issuer-id: ${{ secrets.APPSTORE_KEY_ISSUER_ID }}
|
app-store-key-issuer-id: ${{ secrets.APPSTORE_KEY_ISSUER_ID }}
|
||||||
archive-path: Burrow.xcarchive
|
archive-path: Burrow.xcarchive
|
||||||
- name: Export
|
- name: Export Locally
|
||||||
uses: ./.github/actions/export
|
uses: ./.github/actions/export
|
||||||
with:
|
with:
|
||||||
method: ${{ matrix.platform == 'macOS' && 'developer-id' || 'ad-hoc' }}
|
method: ${{ matrix.configuration['method'] }}
|
||||||
destination: export
|
destination: export
|
||||||
app-store-key: ${{ secrets.APPSTORE_KEY }}
|
app-store-key: ${{ secrets.APPSTORE_KEY }}
|
||||||
app-store-key-id: ${{ secrets.APPSTORE_KEY_ID }}
|
app-store-key-id: ${{ secrets.APPSTORE_KEY_ID }}
|
||||||
app-store-key-issuer-id: ${{ secrets.APPSTORE_KEY_ISSUER_ID }}
|
app-store-key-issuer-id: ${{ secrets.APPSTORE_KEY_ISSUER_ID }}
|
||||||
archive-path: Burrow.xcarchive
|
archive-path: Burrow.xcarchive
|
||||||
export-options: |
|
|
||||||
{"teamID":"P6PV2R9443","destination":"export","method":"developer-id","provisioningProfiles":{"com.hackclub.burrow":"Burrow Developer ID","com.hackclub.burrow.network":"Burrow Network Developer ID"},"signingCertificate":"Developer ID Application","signingStyle":"manual"}
|
|
||||||
export-path: Release
|
export-path: Release
|
||||||
- name: Notarize
|
- name: Compress
|
||||||
if: ${{ matrix.platform == 'macOS' }}
|
if: ${{ matrix.configuration['platform'] == 'macOS' }}
|
||||||
uses: ./.github/actions/notarize
|
|
||||||
with:
|
|
||||||
app-store-key: ${{ secrets.APPSTORE_KEY }}
|
|
||||||
app-store-key-id: ${{ secrets.APPSTORE_KEY_ID }}
|
|
||||||
app-store-key-issuer-id: ${{ secrets.APPSTORE_KEY_ISSUER_ID }}
|
|
||||||
- name: Compress (iOS)
|
|
||||||
if: ${{ matrix.platform == 'iOS' }}
|
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: tar --options xz:compression-level=9 -C Apple/Release -cJf Burrow.app.txz ./
|
||||||
cp Apple/Release/Burrow.ipa Burrow.ipa
|
- name: Attach Artifact
|
||||||
aa archive -a lzma -b 8m -d Apple -subdir Burrow.xcarchive -o Burrow-${{ matrix.platform }}.xcarchive.aar
|
uses: SierraSoftworks/gh-releases@v1.0.6
|
||||||
rm -rf Apple/Release
|
|
||||||
- name: Compress (macOS)
|
|
||||||
if: ${{ matrix.platform == 'macOS' }}
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
aa archive -a lzma -b 8m -d Apple/Release -subdir Burrow.app -o Burrow.app.aar
|
|
||||||
aa archive -a lzma -b 8m -d Apple -subdir Burrow.xcarchive -o Burrow-${{ matrix.platform }}.xcarchive.aar
|
|
||||||
rm -rf Apple/Release
|
|
||||||
- name: Upload to GitHub
|
|
||||||
uses: SierraSoftworks/gh-releases@v1.0.7
|
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
release_tag: ${{ github.ref_name }}
|
overwrite: 'false'
|
||||||
overwrite: 'true'
|
files: ${{ matrix.configuration['artifact-file'] }}
|
||||||
files: |
|
|
||||||
${{ matrix.platform == 'macOS' && 'Burrow.aap.aar' || 'Burrow.ipa' }}
|
|
||||||
Burrow-${{ matrix.platform }}.xcarchive.aar
|
|
||||||
- name: Upload to App Store Connect
|
|
||||||
if: ${{ matrix.platform == 'iOS' }}
|
|
||||||
uses: ./.github/actions/export
|
|
||||||
with:
|
|
||||||
app-store-key: ${{ secrets.APPSTORE_KEY }}
|
|
||||||
app-store-key-id: ${{ secrets.APPSTORE_KEY_ID }}
|
|
||||||
app-store-key-issuer-id: ${{ secrets.APPSTORE_KEY_ISSUER_ID }}
|
|
||||||
archive-path: Burrow.xcarchive
|
|
||||||
export-options: |
|
|
||||||
{"method": "app-store", "destination": "upload"}
|
|
||||||
export-path: Release
|
|
||||||
|
|
|
||||||
23
.github/workflows/release-if-needed.yaml
vendored
|
|
@ -1,23 +0,0 @@
|
||||||
name: Create Release If Needed
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 10 * * *'
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}
|
|
||||||
jobs:
|
|
||||||
create:
|
|
||||||
name: Create Release If Needed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ github.token }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
- shell: bash
|
|
||||||
run: |
|
|
||||||
if [[ $(Tools/version.sh status) == "dirty" ]]; then
|
|
||||||
gh workflow run release-now.yml
|
|
||||||
fi
|
|
||||||
29
.github/workflows/release-linux.yml
vendored
|
|
@ -1,29 +0,0 @@
|
||||||
name: Release (Linux)
|
|
||||||
on:
|
|
||||||
release:
|
|
||||||
types:
|
|
||||||
- created
|
|
||||||
jobs:
|
|
||||||
appimage:
|
|
||||||
name: Build AppImage
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
container: docker
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
- name: Build AppImage
|
|
||||||
run: |
|
|
||||||
docker build -t appimage-builder . -f burrow-gtk/build-aux/Dockerfile
|
|
||||||
docker create --name temp appimage-builder
|
|
||||||
docker cp temp:/app/burrow-gtk/build-appimage/Burrow-x86_64.AppImage .
|
|
||||||
docker rm temp
|
|
||||||
- name: Attach Artifacts
|
|
||||||
uses: SierraSoftworks/gh-releases@v1.0.7
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
release_tag: ${{ github.ref_name }}
|
|
||||||
overwrite: "true"
|
|
||||||
files: |
|
|
||||||
Burrow-x86_64.AppImage
|
|
||||||
17
.github/workflows/release-now.yml
vendored
|
|
@ -1,17 +0,0 @@
|
||||||
name: Create Release
|
|
||||||
on: workflow_dispatch
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}
|
|
||||||
jobs:
|
|
||||||
create:
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GH_RELEASE_TOKEN }}
|
|
||||||
name: Create Release
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
- shell: bash
|
|
||||||
run: Tools/version.sh increment
|
|
||||||
27
.gitignore
vendored
|
|
@ -1,32 +1,5 @@
|
||||||
# Xcode
|
# Xcode
|
||||||
xcuserdata
|
xcuserdata
|
||||||
Apple/build/
|
|
||||||
.derived-data/
|
|
||||||
AuthKey_*.p8
|
|
||||||
burrow-certs-pass.txt
|
|
||||||
*.p12
|
|
||||||
|
|
||||||
# Swift
|
|
||||||
Apple/Package/.swiftpm/
|
|
||||||
|
|
||||||
# Rust
|
# Rust
|
||||||
target/
|
target/
|
||||||
.env
|
|
||||||
|
|
||||||
# Bazel
|
|
||||||
bazel-*
|
|
||||||
|
|
||||||
.DS_STORE
|
|
||||||
.idea/
|
|
||||||
|
|
||||||
tmp/
|
|
||||||
.cache/
|
|
||||||
intake/
|
|
||||||
dist/
|
|
||||||
publish/
|
|
||||||
release/
|
|
||||||
ci-artifacts/
|
|
||||||
|
|
||||||
*.db
|
|
||||||
*.sqlite3
|
|
||||||
*.sock
|
|
||||||
|
|
|
||||||
2
.gitlint
|
|
@ -1,5 +1,5 @@
|
||||||
[general]
|
[general]
|
||||||
ignore=body-changed-file-mention,body-is-missing
|
ignore=body-changed-file-mention
|
||||||
ignore-merge-commits=false
|
ignore-merge-commits=false
|
||||||
ignore-fixup-commits=false
|
ignore-fixup-commits=false
|
||||||
ignore-squash-commits=false
|
ignore-squash-commits=false
|
||||||
|
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
condense_wildcard_suffixes = true
|
|
||||||
format_macro_matchers = true
|
|
||||||
imports_layout = "HorizontalVertical"
|
|
||||||
imports_granularity = "Crate"
|
|
||||||
newline_style = "Unix"
|
|
||||||
overflow_delimited_expr = true
|
|
||||||
reorder_impl_items = true
|
|
||||||
group_imports = "StdExternalCrate"
|
|
||||||
trailing_semicolon = false
|
|
||||||
use_field_init_shorthand = true
|
|
||||||
use_try_shorthand = true
|
|
||||||
struct_lit_width = 30
|
|
||||||
|
|
@ -30,6 +30,7 @@ opt_in_rules:
|
||||||
- function_default_parameter_at_end
|
- function_default_parameter_at_end
|
||||||
- ibinspectable_in_extension
|
- ibinspectable_in_extension
|
||||||
- identical_operands
|
- identical_operands
|
||||||
|
- implicitly_unwrapped_optional
|
||||||
- indentation_width
|
- indentation_width
|
||||||
- joined_default_parameter
|
- joined_default_parameter
|
||||||
- last_where
|
- last_where
|
||||||
|
|
@ -45,6 +46,7 @@ opt_in_rules:
|
||||||
- multiline_parameters
|
- multiline_parameters
|
||||||
- multiline_parameters_brackets
|
- multiline_parameters_brackets
|
||||||
- no_extension_access_modifier
|
- no_extension_access_modifier
|
||||||
|
- no_grouping_extension
|
||||||
- nslocalizedstring_key
|
- nslocalizedstring_key
|
||||||
- nslocalizedstring_require_bundle
|
- nslocalizedstring_require_bundle
|
||||||
- number_separator
|
- number_separator
|
||||||
|
|
@ -74,7 +76,9 @@ opt_in_rules:
|
||||||
- sorted_first_last
|
- sorted_first_last
|
||||||
- sorted_imports
|
- sorted_imports
|
||||||
- static_operator
|
- static_operator
|
||||||
|
- strict_fileprivate
|
||||||
- strong_iboutlet
|
- strong_iboutlet
|
||||||
|
- switch_case_on_newline
|
||||||
- test_case_accessibility
|
- test_case_accessibility
|
||||||
- toggle_bool
|
- toggle_bool
|
||||||
- trailing_closure
|
- trailing_closure
|
||||||
|
|
@ -93,5 +97,3 @@ disabled_rules:
|
||||||
- force_try
|
- force_try
|
||||||
- nesting
|
- nesting
|
||||||
- todo
|
- todo
|
||||||
- trailing_comma
|
|
||||||
- switch_case_on_newline
|
|
||||||
|
|
|
||||||
1
.vscode/extensions.json
vendored
|
|
@ -1,6 +1,5 @@
|
||||||
{
|
{
|
||||||
"recommendations": [
|
"recommendations": [
|
||||||
"rust-lang.rust-analyzer",
|
"rust-lang.rust-analyzer",
|
||||||
"vadimcn.vscode-lldb",
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
38
.vscode/settings.json
vendored
|
|
@ -1,26 +1,16 @@
|
||||||
{
|
{
|
||||||
"files.autoSave": "onFocusChange",
|
"files.autoSave": "onFocusChange",
|
||||||
"files.defaultLanguage": "rust",
|
"files.defaultLanguage": "rust",
|
||||||
"editor.formatOnPaste": true,
|
"explorer.excludeGitIgnore": true,
|
||||||
"editor.formatOnSave": true,
|
"editor.formatOnPaste": true,
|
||||||
"files.trimTrailingWhitespace": true,
|
"editor.formatOnSave": true,
|
||||||
"editor.suggest.preview": true,
|
"files.trimTrailingWhitespace": true,
|
||||||
"editor.acceptSuggestionOnEnter": "on",
|
"editor.suggest.preview": true,
|
||||||
"rust-analyzer.restartServerOnConfigChange": true,
|
"editor.acceptSuggestionOnEnter": "on",
|
||||||
"rust-analyzer.cargo.features": "all",
|
"rust-analyzer.check.command": "clippy",
|
||||||
"rust-analyzer.rustfmt.extraArgs": ["+nightly"],
|
"rust-analyzer.restartServerOnConfigChange": true,
|
||||||
"[rust]": {
|
"rust-analyzer.cargo.features": "all",
|
||||||
"editor.defaultFormatter": "rust-lang.rust-analyzer"
|
"[rust]": {
|
||||||
},
|
"editor.defaultFormatter": "rust-lang.rust-analyzer",
|
||||||
"rust-analyzer.inlayHints.typeHints.enable": false,
|
},
|
||||||
"rust-analyzer.linkedProjects": [
|
|
||||||
"./burrow/Cargo.toml"
|
|
||||||
],
|
|
||||||
"[yaml]": {
|
|
||||||
"editor.insertSpaces": true,
|
|
||||||
"editor.tabSize": 2,
|
|
||||||
"editor.autoIndent": "advanced",
|
|
||||||
"diffEditor.ignoreTrimWhitespace": false,
|
|
||||||
"editor.formatOnSave": false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
12
.vscode/tasks.json
vendored
|
|
@ -3,7 +3,7 @@
|
||||||
"tasks": [
|
"tasks": [
|
||||||
{
|
{
|
||||||
"type": "cargo",
|
"type": "cargo",
|
||||||
"command": "clippy",
|
"command": "check",
|
||||||
"problemMatcher": [
|
"problemMatcher": [
|
||||||
"$rustc"
|
"$rustc"
|
||||||
],
|
],
|
||||||
|
|
@ -11,13 +11,7 @@
|
||||||
"kind": "build",
|
"kind": "build",
|
||||||
"isDefault": true
|
"isDefault": true
|
||||||
},
|
},
|
||||||
"label": "rust: cargo clippy",
|
"label": "Check"
|
||||||
"args": [
|
}
|
||||||
"--workspace",
|
|
||||||
"--all-targets",
|
|
||||||
"--all-features",
|
|
||||||
"--all"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
14
AGENTS.md
|
|
@ -1,14 +0,0 @@
|
||||||
# instructions for agents
|
|
||||||
|
|
||||||
1. Spell the project name as `Burrow` in user-facing copy and `burrow` in code, package, and protocol identifiers unless an existing integration requires a different literal.
|
|
||||||
2. Read [CONSTITUTION.md](CONSTITUTION.md) before changing Apple clients, the daemon, the control plane, forge infrastructure, identity, or security-sensitive code.
|
|
||||||
3. Anchor non-trivial changes in a Burrow Evolution Proposal (BEP) under [evolution/](evolution/README.md) so future contributors can inherit the rationale, safeguards, and rollout shape.
|
|
||||||
4. Before touching the Apple app, daemon IPC, or Tailnet flows, review:
|
|
||||||
- [evolution/proposals/BEP-0002-control-plane-bootstrap-and-local-auth.md](evolution/proposals/BEP-0002-control-plane-bootstrap-and-local-auth.md)
|
|
||||||
- [evolution/proposals/BEP-0003-connect-ip-and-negotiation-roadmap.md](evolution/proposals/BEP-0003-connect-ip-and-negotiation-roadmap.md)
|
|
||||||
- [evolution/proposals/BEP-0005-daemon-ipc-and-apple-boundary.md](evolution/proposals/BEP-0005-daemon-ipc-and-apple-boundary.md)
|
|
||||||
- [evolution/proposals/BEP-0006-tailnet-authority-first-control-plane.md](evolution/proposals/BEP-0006-tailnet-authority-first-control-plane.md)
|
|
||||||
5. Apple clients must talk only to the daemon over gRPC. Do not add direct HTTP, control-plane, or helper-process calls from Swift UI code.
|
|
||||||
6. Treat Tailnet as one protocol family. Tailscale-managed and self-hosted Headscale-style deployments differ by authority, policy, and auth details, not by a separate user-facing protocol surface.
|
|
||||||
7. Maintain canonical identity and operator metadata in [contributors.nix](contributors.nix). If Burrow forge, Authentik, Headscale, or admin/group mappings need to change, edit that registry first and derive runtime configuration from it.
|
|
||||||
8. When process or architecture is unclear, stop and draft or update a BEP instead of improvising durable behavior in code.
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
# Burrow Android
|
|
||||||
|
|
||||||
The Android app starts as a Kotlin shell linked to `crates/burrow-mobile-ffi`,
|
|
||||||
which exposes the cross-platform `burrow-core` crate through JNI.
|
|
||||||
|
|
||||||
The current stub proves the package shape and Rust core boundary. Full VPN
|
|
||||||
support must use Android `VpnService` and keep platform consent, Play Store
|
|
||||||
policy, and disclosure requirements in the release lane.
|
|
||||||
|
|
||||||
The Bazel entrypoint is:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
bazel build //bazel/android:check_stub_stamp
|
|
||||||
```
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
plugins {
|
|
||||||
id("com.android.application")
|
|
||||||
id("org.jetbrains.kotlin.android")
|
|
||||||
}
|
|
||||||
|
|
||||||
android {
|
|
||||||
namespace = "net.burrow.android"
|
|
||||||
compileSdk = 36
|
|
||||||
|
|
||||||
defaultConfig {
|
|
||||||
applicationId = "net.burrow.android"
|
|
||||||
minSdk = 26
|
|
||||||
targetSdk = 36
|
|
||||||
versionCode = 1
|
|
||||||
versionName = "0.1.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
kotlin {
|
|
||||||
jvmToolchain(17)
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<application
|
|
||||||
android:allowBackup="false"
|
|
||||||
android:icon="@mipmap/ic_launcher"
|
|
||||||
android:label="@string/app_name"
|
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
|
||||||
android:supportsRtl="true"
|
|
||||||
android:theme="@style/BurrowTheme">
|
|
||||||
<activity
|
|
||||||
android:name=".MainActivity"
|
|
||||||
android:exported="true">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.MAIN" />
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
</application>
|
|
||||||
</manifest>
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
package net.burrow.android
|
|
||||||
|
|
||||||
object BurrowCore {
|
|
||||||
init {
|
|
||||||
System.loadLibrary("burrow_mobile_ffi")
|
|
||||||
}
|
|
||||||
|
|
||||||
external fun version(): String
|
|
||||||
}
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
package net.burrow.android
|
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.widget.LinearLayout
|
|
||||||
import android.widget.TextView
|
|
||||||
|
|
||||||
class MainActivity : Activity() {
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
|
|
||||||
val versionText = runCatching { BurrowCore.version() }
|
|
||||||
.getOrElse { "burrow-core unavailable" }
|
|
||||||
|
|
||||||
val root = LinearLayout(this).apply {
|
|
||||||
orientation = LinearLayout.VERTICAL
|
|
||||||
setPadding(40, 40, 40, 40)
|
|
||||||
}
|
|
||||||
|
|
||||||
root.addView(TextView(this).apply {
|
|
||||||
text = getString(R.string.app_name)
|
|
||||||
textSize = 24f
|
|
||||||
})
|
|
||||||
|
|
||||||
root.addView(TextView(this).apply {
|
|
||||||
text = versionText
|
|
||||||
textSize = 14f
|
|
||||||
})
|
|
||||||
|
|
||||||
setContentView(root)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 44 KiB |
|
|
@ -1,3 +0,0 @@
|
||||||
<resources>
|
|
||||||
<string name="app_name">Burrow</string>
|
|
||||||
</resources>
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
<resources>
|
|
||||||
<style name="BurrowTheme" parent="android:style/Theme.Material.Light.NoActionBar">
|
|
||||||
<item name="android:fontFamily">sans</item>
|
|
||||||
<item name="android:windowLightStatusBar">true</item>
|
|
||||||
<item name="android:navigationBarColor">#ffffff</item>
|
|
||||||
<item name="android:statusBarColor">#ffffff</item>
|
|
||||||
</style>
|
|
||||||
</resources>
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
plugins {
|
|
||||||
id("com.android.application") version "8.10.1" apply false
|
|
||||||
id("org.jetbrains.kotlin.android") version "2.1.21" apply false
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
pluginManagement {
|
|
||||||
repositories {
|
|
||||||
google()
|
|
||||||
mavenCentral()
|
|
||||||
gradlePluginPortal()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencyResolutionManagement {
|
|
||||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
|
||||||
repositories {
|
|
||||||
google()
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rootProject.name = "BurrowAndroid"
|
|
||||||
include(":app")
|
|
||||||
|
|
@ -2,15 +2,6 @@
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>com.apple.developer.associated-domains</key>
|
|
||||||
<array>
|
|
||||||
<string>applinks:burrow.rs?mode=developer</string>
|
|
||||||
<string>webcredentials:burrow.rs?mode=developer</string>
|
|
||||||
</array>
|
|
||||||
<key>com.apple.developer.networking.networkextension</key>
|
|
||||||
<array>
|
|
||||||
<string>packet-tunnel-provider</string>
|
|
||||||
</array>
|
|
||||||
<key>com.apple.security.application-groups</key>
|
<key>com.apple.security.application-groups</key>
|
||||||
<array>
|
<array>
|
||||||
<string>$(APP_GROUP_IDENTIFIER)</string>
|
<string>$(APP_GROUP_IDENTIFIER)</string>
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,6 @@
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>com.apple.developer.associated-domains</key>
|
|
||||||
<array>
|
|
||||||
<string>applinks:burrow.rs?mode=developer</string>
|
|
||||||
<string>webcredentials:burrow.rs?mode=developer</string>
|
|
||||||
</array>
|
|
||||||
<key>com.apple.developer.networking.networkextension</key>
|
|
||||||
<array>
|
|
||||||
<string>packet-tunnel-provider</string>
|
|
||||||
</array>
|
|
||||||
<key>com.apple.security.application-groups</key>
|
<key>com.apple.security.application-groups</key>
|
||||||
<array>
|
<array>
|
||||||
<string>$(APP_GROUP_IDENTIFIER)</string>
|
<string>$(APP_GROUP_IDENTIFIER)</string>
|
||||||
|
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
#include "../Configuration/App.xcconfig"
|
|
||||||
|
|
||||||
PRODUCT_NAME = Burrow
|
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = $(APP_BUNDLE_IDENTIFIER)
|
|
||||||
PRODUCT_MODULE_NAME = BurrowApp
|
|
||||||
|
|
||||||
INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphone*] = YES
|
|
||||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphone*] = YES
|
|
||||||
INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphone*] = YES
|
|
||||||
INFOPLIST_KEY_UIStatusBarStyle[sdk=iphone*] = UIStatusBarStyleDefault
|
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad[sdk=iphone*] = UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight
|
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone[sdk=iphone*] = UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight
|
|
||||||
ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES[sdk=iphone*] = BurrowPanel02 BurrowPanel03 BurrowPanel04 BurrowPanel05 BurrowPanel06
|
|
||||||
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS[sdk=iphone*] = YES
|
|
||||||
TARGETED_DEVICE_FAMILY[sdk=iphone*] = 1,2
|
|
||||||
EXCLUDED_SOURCE_FILE_NAMES = MainMenu.xib
|
|
||||||
|
|
||||||
EXCLUDED_SOURCE_FILE_NAMES[sdk=macosx*] =
|
|
||||||
INFOPLIST_KEY_LSUIElement[sdk=macosx*] = YES
|
|
||||||
INFOPLIST_KEY_NSMainNibFile[sdk=macosx*] = MainMenu
|
|
||||||
INFOPLIST_KEY_NSPrincipalClass[sdk=macosx*] = NSApplication
|
|
||||||
INFOPLIST_KEY_LSApplicationCategoryType[sdk=macosx*] = public.app-category.utilities
|
|
||||||
BURROW_SPARKLE_FEED_URL = https:/$()/releases.burrow.net/sparkle/appcast.xml
|
|
||||||
BURROW_SPARKLE_PUBLIC_ED_KEY = uugZuJeqvvKd91NZ6F1Fv2cQenUbIG/ZW3L9MuaEz30=
|
|
||||||
INFOPLIST_KEY_SUFeedURL[sdk=macosx*] = $(BURROW_SPARKLE_FEED_URL)
|
|
||||||
INFOPLIST_KEY_SUPublicEDKey[sdk=macosx*] = $(BURROW_SPARKLE_PUBLIC_ED_KEY)
|
|
||||||
|
|
||||||
CODE_SIGN_ENTITLEMENTS = App/App-iOS.entitlements
|
|
||||||
CODE_SIGN_ENTITLEMENTS[sdk=macosx*] = App/App-macOS.entitlements
|
|
||||||
|
|
@ -1,112 +0,0 @@
|
||||||
#if os(macOS)
|
|
||||||
import AppKit
|
|
||||||
import BurrowUI
|
|
||||||
import Sparkle
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
@main
|
|
||||||
@MainActor
|
|
||||||
class AppDelegate: NSObject, NSApplicationDelegate {
|
|
||||||
private var windowController: NSWindowController?
|
|
||||||
private let updaterController = SPUStandardUpdaterController(
|
|
||||||
startingUpdater: true,
|
|
||||||
updaterDelegate: nil,
|
|
||||||
userDriverDelegate: nil
|
|
||||||
)
|
|
||||||
|
|
||||||
private let quitItem: NSMenuItem = {
|
|
||||||
let quitItem = NSMenuItem(
|
|
||||||
title: "Quit Burrow",
|
|
||||||
action: #selector(NSApplication.terminate(_:)),
|
|
||||||
keyEquivalent: "q"
|
|
||||||
)
|
|
||||||
quitItem.target = NSApplication.shared
|
|
||||||
quitItem.keyEquivalentModifierMask = .command
|
|
||||||
return quitItem
|
|
||||||
}()
|
|
||||||
|
|
||||||
private lazy var openItem: NSMenuItem = {
|
|
||||||
let item = NSMenuItem(
|
|
||||||
title: "Open Burrow",
|
|
||||||
action: #selector(openWindow),
|
|
||||||
keyEquivalent: "o"
|
|
||||||
)
|
|
||||||
item.target = self
|
|
||||||
item.keyEquivalentModifierMask = .command
|
|
||||||
return item
|
|
||||||
}()
|
|
||||||
|
|
||||||
private lazy var checkForUpdatesItem: NSMenuItem = {
|
|
||||||
let item = NSMenuItem(
|
|
||||||
title: "Check for Updates...",
|
|
||||||
action: #selector(checkForUpdates(_:)),
|
|
||||||
keyEquivalent: ""
|
|
||||||
)
|
|
||||||
item.target = self
|
|
||||||
return item
|
|
||||||
}()
|
|
||||||
|
|
||||||
private let toggleItem: NSMenuItem = {
|
|
||||||
let toggleView = NSHostingView(rootView: MenuItemToggleView())
|
|
||||||
toggleView.frame.size = CGSize(width: 300, height: 32)
|
|
||||||
toggleView.autoresizingMask = [.width]
|
|
||||||
|
|
||||||
let toggleItem = NSMenuItem()
|
|
||||||
toggleItem.view = toggleView
|
|
||||||
return toggleItem
|
|
||||||
}()
|
|
||||||
|
|
||||||
private lazy var menu: NSMenu = {
|
|
||||||
let menu = NSMenu()
|
|
||||||
menu.items = [
|
|
||||||
toggleItem,
|
|
||||||
openItem,
|
|
||||||
checkForUpdatesItem,
|
|
||||||
.separator(),
|
|
||||||
quitItem
|
|
||||||
]
|
|
||||||
return menu
|
|
||||||
}()
|
|
||||||
|
|
||||||
private lazy var statusItem: NSStatusItem = {
|
|
||||||
let statusBar = NSStatusBar.system
|
|
||||||
let statusItem = statusBar.statusItem(withLength: NSStatusItem.squareLength)
|
|
||||||
if let button = statusItem.button {
|
|
||||||
button.image = NSImage(systemSymbolName: "pipe.and.drop.fill", accessibilityDescription: nil)
|
|
||||||
}
|
|
||||||
return statusItem
|
|
||||||
}()
|
|
||||||
|
|
||||||
func applicationDidFinishLaunching(_ notification: Notification) {
|
|
||||||
statusItem.menu = menu
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc
|
|
||||||
private func openWindow() {
|
|
||||||
if let window = windowController?.window {
|
|
||||||
window.makeKeyAndOrderFront(nil)
|
|
||||||
NSApplication.shared.activate(ignoringOtherApps: true)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let contentView = BurrowView()
|
|
||||||
let hostingController = NSHostingController(rootView: contentView)
|
|
||||||
let window = NSWindow(contentViewController: hostingController)
|
|
||||||
window.title = "Burrow"
|
|
||||||
window.setContentSize(NSSize(width: 820, height: 720))
|
|
||||||
window.styleMask.insert([.titled, .closable, .miniaturizable, .resizable])
|
|
||||||
window.center()
|
|
||||||
|
|
||||||
let controller = NSWindowController(window: window)
|
|
||||||
controller.shouldCascadeWindows = true
|
|
||||||
controller.showWindow(nil)
|
|
||||||
windowController = controller
|
|
||||||
NSApplication.shared.activate(ignoringOtherApps: true)
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc
|
|
||||||
private func checkForUpdates(_ sender: Any?) {
|
|
||||||
updaterController.checkForUpdates(sender)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
11
Apple/App/Assets.xcassets/AccentColor.colorset/Contents.json
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
63
Apple/App/Assets.xcassets/AppIcon.appiconset/Contents.json
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"size" : "1024x1024"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "mac",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "16x16"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "mac",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "16x16"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "mac",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "32x32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "mac",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "32x32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "mac",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "128x128"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "mac",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "128x128"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "mac",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "256x256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "mac",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "256x256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "mac",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "512x512"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "mac",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "512x512"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
17
Apple/App/Burrow.xcconfig
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#include "../Configuration/App.xcconfig"
|
||||||
|
|
||||||
|
PRODUCT_NAME = Burrow
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = $(APP_BUNDLE_IDENTIFIER)
|
||||||
|
|
||||||
|
INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphone*] = YES
|
||||||
|
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphone*] = YES
|
||||||
|
INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphone*] = YES
|
||||||
|
INFOPLIST_KEY_UIStatusBarStyle[sdk=iphone*] = UIStatusBarStyleDefault
|
||||||
|
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad[sdk=iphone*] = UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight
|
||||||
|
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone[sdk=iphone*] = UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight
|
||||||
|
TARGETED_DEVICE_FAMILY[sdk=iphone*] = 1,2
|
||||||
|
|
||||||
|
INFOPLIST_KEY_LSApplicationCategoryType[sdk=macos*] = public.app-category.utilities
|
||||||
|
|
||||||
|
CODE_SIGN_ENTITLEMENTS = App/App-iOS.entitlements
|
||||||
|
CODE_SIGN_ENTITLEMENTS[sdk=macos*] = App/App-macOS.entitlements
|
||||||
|
|
@ -1,46 +1,10 @@
|
||||||
#if !os(macOS)
|
|
||||||
import BurrowUI
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
#if os(iOS)
|
|
||||||
import UIKit
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@MainActor
|
|
||||||
@main
|
@main
|
||||||
struct BurrowApp: App {
|
struct BurrowApp: App {
|
||||||
var body: some Scene {
|
var body: some Scene {
|
||||||
WindowGroup {
|
WindowGroup {
|
||||||
#if os(iOS)
|
ContentView()
|
||||||
BurrowView(appIconManager: UIKitAppIconManager())
|
|
||||||
#else
|
|
||||||
BurrowView()
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if os(iOS)
|
|
||||||
@MainActor
|
|
||||||
private struct UIKitAppIconManager: AppIconManaging {
|
|
||||||
var supportsAlternateIcons: Bool {
|
|
||||||
UIApplication.shared.supportsAlternateIcons
|
|
||||||
}
|
|
||||||
|
|
||||||
var alternateIconName: String? {
|
|
||||||
UIApplication.shared.alternateIconName
|
|
||||||
}
|
|
||||||
|
|
||||||
func setAlternateIconName(_ iconName: String?) async throws {
|
|
||||||
try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<Void, any Error>) in
|
|
||||||
UIApplication.shared.setAlternateIconName(iconName) { error in
|
|
||||||
if let error {
|
|
||||||
continuation.resume(throwing: error)
|
|
||||||
} else {
|
|
||||||
continuation.resume(returning: ())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
|
||||||
19
Apple/App/ContentView.swift
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct ContentView: View {
|
||||||
|
var body: some View {
|
||||||
|
VStack {
|
||||||
|
Image(systemName: "globe")
|
||||||
|
.imageScale(.large)
|
||||||
|
.foregroundColor(.accentColor)
|
||||||
|
Text("Hello, world!")
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ContentView_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
ContentView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,679 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="23091" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
|
||||||
<dependencies>
|
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="23091"/>
|
|
||||||
</dependencies>
|
|
||||||
<objects>
|
|
||||||
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
|
|
||||||
<connections>
|
|
||||||
<outlet property="delegate" destination="Voe-Tx-rLC" id="GzC-gU-4Uq"/>
|
|
||||||
</connections>
|
|
||||||
</customObject>
|
|
||||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
|
||||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
|
||||||
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="BurrowApp" customModuleProvider="target"/>
|
|
||||||
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
|
|
||||||
<menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
|
|
||||||
<items>
|
|
||||||
<menuItem title="Burrow" id="1Xt-HY-uBw">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<menu key="submenu" title="Burrow" systemMenu="apple" id="uQy-DD-JDr">
|
|
||||||
<items>
|
|
||||||
<menuItem title="About Burrow" id="5kV-Vb-QxS">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="orderFrontStandardAboutPanel:" target="-1" id="Exp-CZ-Vem"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
|
|
||||||
<menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/>
|
|
||||||
<menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
|
|
||||||
<menuItem title="Services" id="NMo-om-nkz">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
|
|
||||||
<menuItem title="Hide Burrow" keyEquivalent="h" id="Olw-nP-bQN">
|
|
||||||
<connections>
|
|
||||||
<action selector="hide:" target="-1" id="PnN-Uc-m68"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="hideOtherApplications:" target="-1" id="VT4-aY-XCT"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Show All" id="Kd2-mp-pUS">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="unhideAllApplications:" target="-1" id="Dhg-Le-xox"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
|
|
||||||
<menuItem title="Quit Burrow" keyEquivalent="q" id="4sb-4s-VLi">
|
|
||||||
<connections>
|
|
||||||
<action selector="terminate:" target="-1" id="Te7-pn-YzF"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
</items>
|
|
||||||
</menu>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="File" id="dMs-cI-mzQ">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<menu key="submenu" title="File" id="bib-Uj-vzu">
|
|
||||||
<items>
|
|
||||||
<menuItem title="New" keyEquivalent="n" id="Was-JA-tGl">
|
|
||||||
<connections>
|
|
||||||
<action selector="newDocument:" target="-1" id="4Si-XN-c54"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Open…" keyEquivalent="o" id="IAo-SY-fd9">
|
|
||||||
<connections>
|
|
||||||
<action selector="openDocument:" target="-1" id="bVn-NM-KNZ"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Open Recent" id="tXI-mr-wws">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="oas-Oc-fiZ">
|
|
||||||
<items>
|
|
||||||
<menuItem title="Clear Menu" id="vNY-rz-j42">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="clearRecentDocuments:" target="-1" id="Daa-9d-B3U"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
</items>
|
|
||||||
</menu>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem isSeparatorItem="YES" id="m54-Is-iLE"/>
|
|
||||||
<menuItem title="Close" keyEquivalent="w" id="DVo-aG-piG">
|
|
||||||
<connections>
|
|
||||||
<action selector="performClose:" target="-1" id="HmO-Ls-i7Q"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Save…" keyEquivalent="s" id="pxx-59-PXV">
|
|
||||||
<connections>
|
|
||||||
<action selector="saveDocument:" target="-1" id="teZ-XB-qJY"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Save As…" keyEquivalent="S" id="Bw7-FT-i3A">
|
|
||||||
<connections>
|
|
||||||
<action selector="saveDocumentAs:" target="-1" id="mDf-zr-I0C"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Revert to Saved" keyEquivalent="r" id="KaW-ft-85H">
|
|
||||||
<connections>
|
|
||||||
<action selector="revertDocumentToSaved:" target="-1" id="iJ3-Pv-kwq"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem isSeparatorItem="YES" id="aJh-i4-bef"/>
|
|
||||||
<menuItem title="Page Setup…" keyEquivalent="P" id="qIS-W8-SiK">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="runPageLayout:" target="-1" id="Din-rz-gC5"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Print…" keyEquivalent="p" id="aTl-1u-JFS">
|
|
||||||
<connections>
|
|
||||||
<action selector="print:" target="-1" id="qaZ-4w-aoO"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
</items>
|
|
||||||
</menu>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Edit" id="5QF-Oa-p0T">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<menu key="submenu" title="Edit" id="W48-6f-4Dl">
|
|
||||||
<items>
|
|
||||||
<menuItem title="Undo" keyEquivalent="z" id="dRJ-4n-Yzg">
|
|
||||||
<connections>
|
|
||||||
<action selector="undo:" target="-1" id="M6e-cu-g7V"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Redo" keyEquivalent="Z" id="6dh-zS-Vam">
|
|
||||||
<connections>
|
|
||||||
<action selector="redo:" target="-1" id="oIA-Rs-6OD"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem isSeparatorItem="YES" id="WRV-NI-Exz"/>
|
|
||||||
<menuItem title="Cut" keyEquivalent="x" id="uRl-iY-unG">
|
|
||||||
<connections>
|
|
||||||
<action selector="cut:" target="-1" id="YJe-68-I9s"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Copy" keyEquivalent="c" id="x3v-GG-iWU">
|
|
||||||
<connections>
|
|
||||||
<action selector="copy:" target="-1" id="G1f-GL-Joy"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Paste" keyEquivalent="v" id="gVA-U4-sdL">
|
|
||||||
<connections>
|
|
||||||
<action selector="paste:" target="-1" id="UvS-8e-Qdg"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Paste and Match Style" keyEquivalent="V" id="WeT-3V-zwk">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="pasteAsPlainText:" target="-1" id="cEh-KX-wJQ"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Delete" id="pa3-QI-u2k">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="delete:" target="-1" id="0Mk-Ml-PaM"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m">
|
|
||||||
<connections>
|
|
||||||
<action selector="selectAll:" target="-1" id="VNm-Mi-diN"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem isSeparatorItem="YES" id="uyl-h8-XO2"/>
|
|
||||||
<menuItem title="Find" id="4EN-yA-p0u">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<menu key="submenu" title="Find" id="1b7-l0-nxx">
|
|
||||||
<items>
|
|
||||||
<menuItem title="Find…" tag="1" keyEquivalent="f" id="Xz5-n4-O0W">
|
|
||||||
<connections>
|
|
||||||
<action selector="performFindPanelAction:" target="-1" id="cD7-Qs-BN4"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="YEy-JH-Tfz">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="performFindPanelAction:" target="-1" id="WD3-Gg-5AJ"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Find Next" tag="2" keyEquivalent="g" id="q09-fT-Sye">
|
|
||||||
<connections>
|
|
||||||
<action selector="performFindPanelAction:" target="-1" id="NDo-RZ-v9R"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Find Previous" tag="3" keyEquivalent="G" id="OwM-mh-QMV">
|
|
||||||
<connections>
|
|
||||||
<action selector="performFindPanelAction:" target="-1" id="HOh-sY-3ay"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="buJ-ug-pKt">
|
|
||||||
<connections>
|
|
||||||
<action selector="performFindPanelAction:" target="-1" id="U76-nv-p5D"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Jump to Selection" keyEquivalent="j" id="S0p-oC-mLd">
|
|
||||||
<connections>
|
|
||||||
<action selector="centerSelectionInVisibleArea:" target="-1" id="IOG-6D-g5B"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
</items>
|
|
||||||
</menu>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Spelling and Grammar" id="Dv1-io-Yv7">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<menu key="submenu" title="Spelling" id="3IN-sU-3Bg">
|
|
||||||
<items>
|
|
||||||
<menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="HFo-cy-zxI">
|
|
||||||
<connections>
|
|
||||||
<action selector="showGuessPanel:" target="-1" id="vFj-Ks-hy3"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Check Document Now" keyEquivalent=";" id="hz2-CU-CR7">
|
|
||||||
<connections>
|
|
||||||
<action selector="checkSpelling:" target="-1" id="fz7-VC-reM"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem isSeparatorItem="YES" id="bNw-od-mp5"/>
|
|
||||||
<menuItem title="Check Spelling While Typing" id="rbD-Rh-wIN">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="toggleContinuousSpellChecking:" target="-1" id="7w6-Qz-0kB"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Check Grammar With Spelling" id="mK6-2p-4JG">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="toggleGrammarChecking:" target="-1" id="muD-Qn-j4w"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Correct Spelling Automatically" id="78Y-hA-62v">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="toggleAutomaticSpellingCorrection:" target="-1" id="2lM-Qi-WAP"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
</items>
|
|
||||||
</menu>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Substitutions" id="9ic-FL-obx">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<menu key="submenu" title="Substitutions" id="FeM-D8-WVr">
|
|
||||||
<items>
|
|
||||||
<menuItem title="Show Substitutions" id="z6F-FW-3nz">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="orderFrontSubstitutionsPanel:" target="-1" id="oku-mr-iSq"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem isSeparatorItem="YES" id="gPx-C9-uUO"/>
|
|
||||||
<menuItem title="Smart Copy/Paste" id="9yt-4B-nSM">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="toggleSmartInsertDelete:" target="-1" id="3IJ-Se-DZD"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Smart Quotes" id="hQb-2v-fYv">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="ptq-xd-QOA"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Smart Dashes" id="rgM-f4-ycn">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="toggleAutomaticDashSubstitution:" target="-1" id="oCt-pO-9gS"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Smart Links" id="cwL-P1-jid">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="toggleAutomaticLinkDetection:" target="-1" id="Gip-E3-Fov"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Data Detectors" id="tRr-pd-1PS">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="toggleAutomaticDataDetection:" target="-1" id="R1I-Nq-Kbl"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Text Replacement" id="HFQ-gK-NFA">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="toggleAutomaticTextReplacement:" target="-1" id="DvP-Fe-Py6"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
</items>
|
|
||||||
</menu>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Transformations" id="2oI-Rn-ZJC">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<menu key="submenu" title="Transformations" id="c8a-y6-VQd">
|
|
||||||
<items>
|
|
||||||
<menuItem title="Make Upper Case" id="vmV-6d-7jI">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="uppercaseWord:" target="-1" id="sPh-Tk-edu"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Make Lower Case" id="d9M-CD-aMd">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="lowercaseWord:" target="-1" id="iUZ-b5-hil"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Capitalize" id="UEZ-Bs-lqG">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="capitalizeWord:" target="-1" id="26H-TL-nsh"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
</items>
|
|
||||||
</menu>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Speech" id="xrE-MZ-jX0">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<menu key="submenu" title="Speech" id="3rS-ZA-NoH">
|
|
||||||
<items>
|
|
||||||
<menuItem title="Start Speaking" id="Ynk-f8-cLZ">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="startSpeaking:" target="-1" id="654-Ng-kyl"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Stop Speaking" id="Oyz-dy-DGm">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="stopSpeaking:" target="-1" id="dX8-6p-jy9"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
</items>
|
|
||||||
</menu>
|
|
||||||
</menuItem>
|
|
||||||
</items>
|
|
||||||
</menu>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Format" id="jxT-CU-nIS">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<menu key="submenu" title="Format" id="GEO-Iw-cKr">
|
|
||||||
<items>
|
|
||||||
<menuItem title="Font" id="Gi5-1S-RQB">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<menu key="submenu" title="Font" systemMenu="font" id="aXa-aM-Jaq">
|
|
||||||
<items>
|
|
||||||
<menuItem title="Show Fonts" keyEquivalent="t" id="Q5e-8K-NDq">
|
|
||||||
<connections>
|
|
||||||
<action selector="orderFrontFontPanel:" target="YLy-65-1bz" id="WHr-nq-2xA"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Bold" tag="2" keyEquivalent="b" id="GB9-OM-e27">
|
|
||||||
<connections>
|
|
||||||
<action selector="addFontTrait:" target="YLy-65-1bz" id="hqk-hr-sYV"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Italic" tag="1" keyEquivalent="i" id="Vjx-xi-njq">
|
|
||||||
<connections>
|
|
||||||
<action selector="addFontTrait:" target="YLy-65-1bz" id="IHV-OB-c03"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Underline" keyEquivalent="u" id="WRG-CD-K1S">
|
|
||||||
<connections>
|
|
||||||
<action selector="underline:" target="-1" id="FYS-2b-JAY"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem isSeparatorItem="YES" id="5gT-KC-WSO"/>
|
|
||||||
<menuItem title="Bigger" tag="3" keyEquivalent="+" id="Ptp-SP-VEL">
|
|
||||||
<connections>
|
|
||||||
<action selector="modifyFont:" target="YLy-65-1bz" id="Uc7-di-UnL"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Smaller" tag="4" keyEquivalent="-" id="i1d-Er-qST">
|
|
||||||
<connections>
|
|
||||||
<action selector="modifyFont:" target="YLy-65-1bz" id="HcX-Lf-eNd"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem isSeparatorItem="YES" id="kx3-Dk-x3B"/>
|
|
||||||
<menuItem title="Kern" id="jBQ-r6-VK2">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<menu key="submenu" title="Kern" id="tlD-Oa-oAM">
|
|
||||||
<items>
|
|
||||||
<menuItem title="Use Default" id="GUa-eO-cwY">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="useStandardKerning:" target="-1" id="6dk-9l-Ckg"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Use None" id="cDB-IK-hbR">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="turnOffKerning:" target="-1" id="U8a-gz-Maa"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Tighten" id="46P-cB-AYj">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="tightenKerning:" target="-1" id="hr7-Nz-8ro"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Loosen" id="ogc-rX-tC1">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="loosenKerning:" target="-1" id="8i4-f9-FKE"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
</items>
|
|
||||||
</menu>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Ligatures" id="o6e-r0-MWq">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<menu key="submenu" title="Ligatures" id="w0m-vy-SC9">
|
|
||||||
<items>
|
|
||||||
<menuItem title="Use Default" id="agt-UL-0e3">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="useStandardLigatures:" target="-1" id="7uR-wd-Dx6"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Use None" id="J7y-lM-qPV">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="turnOffLigatures:" target="-1" id="iX2-gA-Ilz"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Use All" id="xQD-1f-W4t">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="useAllLigatures:" target="-1" id="KcB-kA-TuK"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
</items>
|
|
||||||
</menu>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Baseline" id="OaQ-X3-Vso">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<menu key="submenu" title="Baseline" id="ijk-EB-dga">
|
|
||||||
<items>
|
|
||||||
<menuItem title="Use Default" id="3Om-Ey-2VK">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="unscript:" target="-1" id="0vZ-95-Ywn"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Superscript" id="Rqc-34-cIF">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="superscript:" target="-1" id="3qV-fo-wpU"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Subscript" id="I0S-gh-46l">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="subscript:" target="-1" id="Q6W-4W-IGz"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Raise" id="2h7-ER-AoG">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="raiseBaseline:" target="-1" id="4sk-31-7Q9"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Lower" id="1tx-W0-xDw">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="lowerBaseline:" target="-1" id="OF1-bc-KW4"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
</items>
|
|
||||||
</menu>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem isSeparatorItem="YES" id="Ndw-q3-faq"/>
|
|
||||||
<menuItem title="Show Colors" keyEquivalent="C" id="bgn-CT-cEk">
|
|
||||||
<connections>
|
|
||||||
<action selector="orderFrontColorPanel:" target="-1" id="mSX-Xz-DV3"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem isSeparatorItem="YES" id="iMs-zA-UFJ"/>
|
|
||||||
<menuItem title="Copy Style" keyEquivalent="c" id="5Vv-lz-BsD">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="copyFont:" target="-1" id="GJO-xA-L4q"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Paste Style" keyEquivalent="v" id="vKC-jM-MkH">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="pasteFont:" target="-1" id="JfD-CL-leO"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
</items>
|
|
||||||
</menu>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Text" id="Fal-I4-PZk">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<menu key="submenu" title="Text" id="d9c-me-L2H">
|
|
||||||
<items>
|
|
||||||
<menuItem title="Align Left" keyEquivalent="{" id="ZM1-6Q-yy1">
|
|
||||||
<connections>
|
|
||||||
<action selector="alignLeft:" target="-1" id="zUv-R1-uAa"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Center" keyEquivalent="|" id="VIY-Ag-zcb">
|
|
||||||
<connections>
|
|
||||||
<action selector="alignCenter:" target="-1" id="spX-mk-kcS"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Justify" id="J5U-5w-g23">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="alignJustified:" target="-1" id="ljL-7U-jND"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Align Right" keyEquivalent="}" id="wb2-vD-lq4">
|
|
||||||
<connections>
|
|
||||||
<action selector="alignRight:" target="-1" id="r48-bG-YeY"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem isSeparatorItem="YES" id="4s2-GY-VfK"/>
|
|
||||||
<menuItem title="Writing Direction" id="H1b-Si-o9J">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<menu key="submenu" title="Writing Direction" id="8mr-sm-Yjd">
|
|
||||||
<items>
|
|
||||||
<menuItem title="Paragraph" enabled="NO" id="ZvO-Gk-QUH">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem id="YGs-j5-SAR">
|
|
||||||
<string key="title"> Default</string>
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="makeBaseWritingDirectionNatural:" target="-1" id="qtV-5e-UBP"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem id="Lbh-J2-qVU">
|
|
||||||
<string key="title"> Left to Right</string>
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="makeBaseWritingDirectionLeftToRight:" target="-1" id="S0X-9S-QSf"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem id="jFq-tB-4Kx">
|
|
||||||
<string key="title"> Right to Left</string>
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="makeBaseWritingDirectionRightToLeft:" target="-1" id="5fk-qB-AqJ"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem isSeparatorItem="YES" id="swp-gr-a21"/>
|
|
||||||
<menuItem title="Selection" enabled="NO" id="cqv-fj-IhA">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem id="Nop-cj-93Q">
|
|
||||||
<string key="title"> Default</string>
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="makeTextWritingDirectionNatural:" target="-1" id="lPI-Se-ZHp"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem id="BgM-ve-c93">
|
|
||||||
<string key="title"> Left to Right</string>
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="makeTextWritingDirectionLeftToRight:" target="-1" id="caW-Bv-w94"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem id="RB4-Sm-HuC">
|
|
||||||
<string key="title"> Right to Left</string>
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="makeTextWritingDirectionRightToLeft:" target="-1" id="EXD-6r-ZUu"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
</items>
|
|
||||||
</menu>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem isSeparatorItem="YES" id="fKy-g9-1gm"/>
|
|
||||||
<menuItem title="Show Ruler" id="vLm-3I-IUL">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="toggleRuler:" target="-1" id="FOx-HJ-KwY"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Copy Ruler" keyEquivalent="c" id="MkV-Pr-PK5">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="copyRuler:" target="-1" id="71i-fW-3W2"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Paste Ruler" keyEquivalent="v" id="LVM-kO-fVI">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="pasteRuler:" target="-1" id="cSh-wd-qM2"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
</items>
|
|
||||||
</menu>
|
|
||||||
</menuItem>
|
|
||||||
</items>
|
|
||||||
</menu>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="View" id="H8h-7b-M4v">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<menu key="submenu" title="View" id="HyV-fh-RgO">
|
|
||||||
<items>
|
|
||||||
<menuItem title="Show Toolbar" keyEquivalent="t" id="snW-S8-Cw5">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="toggleToolbarShown:" target="-1" id="BXY-wc-z0C"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Customize Toolbar…" id="1UK-8n-QPP">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="runToolbarCustomizationPalette:" target="-1" id="pQI-g3-MTW"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem isSeparatorItem="YES" id="hB3-LF-h0Y"/>
|
|
||||||
<menuItem title="Show Sidebar" keyEquivalent="s" id="kIP-vf-haE">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="toggleSidebar:" target="-1" id="iwa-gc-5KM"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Enter Full Screen" keyEquivalent="f" id="4J7-dP-txa">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="toggleFullScreen:" target="-1" id="dU3-MA-1Rq"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
</items>
|
|
||||||
</menu>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Window" id="aUF-d1-5bR">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
|
|
||||||
<items>
|
|
||||||
<menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
|
|
||||||
<connections>
|
|
||||||
<action selector="performMiniaturize:" target="-1" id="VwT-WD-YPe"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Zoom" id="R4o-n2-Eq4">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="performZoom:" target="-1" id="DIl-cC-cCs"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
|
|
||||||
<menuItem title="Bring All to Front" id="LE2-aR-0XJ">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<connections>
|
|
||||||
<action selector="arrangeInFront:" target="-1" id="DRN-fu-gQh"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
</items>
|
|
||||||
</menu>
|
|
||||||
</menuItem>
|
|
||||||
<menuItem title="Help" id="wpr-3q-Mcd">
|
|
||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
|
||||||
<menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ">
|
|
||||||
<items>
|
|
||||||
<menuItem title="Burrow Help" keyEquivalent="?" id="FKE-Sm-Kum">
|
|
||||||
<connections>
|
|
||||||
<action selector="showHelp:" target="-1" id="y7X-2Q-9no"/>
|
|
||||||
</connections>
|
|
||||||
</menuItem>
|
|
||||||
</items>
|
|
||||||
</menu>
|
|
||||||
</menuItem>
|
|
||||||
</items>
|
|
||||||
<point key="canvasLocation" x="200" y="121"/>
|
|
||||||
</menu>
|
|
||||||
</objects>
|
|
||||||
</document>
|
|
||||||
|
|
@ -1,439 +0,0 @@
|
||||||
import XCTest
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
@MainActor
|
|
||||||
final class BurrowTailnetLoginUITests: XCTestCase {
|
|
||||||
private enum TailnetLoginMode: String, Decodable {
|
|
||||||
case tailscale
|
|
||||||
case discovered
|
|
||||||
}
|
|
||||||
|
|
||||||
private struct TestConfig: Decodable {
|
|
||||||
let email: String
|
|
||||||
let username: String
|
|
||||||
let password: String
|
|
||||||
let mode: TailnetLoginMode?
|
|
||||||
}
|
|
||||||
|
|
||||||
override func setUpWithError() throws {
|
|
||||||
continueAfterFailure = false
|
|
||||||
}
|
|
||||||
|
|
||||||
func testTailnetLoginThroughAuthentikWebSession() throws {
|
|
||||||
let config = try loadTestConfig()
|
|
||||||
let email = config.email
|
|
||||||
let username = config.username
|
|
||||||
let password = config.password
|
|
||||||
let mode = config.mode ?? .tailscale
|
|
||||||
let browserIdentity = mode == .tailscale ? email : username
|
|
||||||
|
|
||||||
let app = XCUIApplication()
|
|
||||||
app.launch()
|
|
||||||
|
|
||||||
let tailnetButton = app.buttons["quick-add-tailnet"]
|
|
||||||
XCTAssertTrue(tailnetButton.waitForExistence(timeout: 15), "Tailnet add button did not appear")
|
|
||||||
tailnetButton.tap()
|
|
||||||
|
|
||||||
configureTailnetIfNeeded(in: app, mode: mode)
|
|
||||||
|
|
||||||
let discoveryField = app.textFields["tailnet-discovery-email"]
|
|
||||||
XCTAssertTrue(discoveryField.waitForExistence(timeout: 10), "Tailnet discovery email field did not appear")
|
|
||||||
replaceText(in: discoveryField, with: email)
|
|
||||||
|
|
||||||
let serverCard = app.descendants(matching: .any)
|
|
||||||
.matching(identifier: "tailnet-server-card")
|
|
||||||
.firstMatch
|
|
||||||
XCTAssertTrue(serverCard.waitForExistence(timeout: 5), "Tailnet server card did not appear")
|
|
||||||
|
|
||||||
let signInButton = app.buttons["tailnet-start-sign-in"]
|
|
||||||
XCTAssertTrue(signInButton.waitForExistence(timeout: 10), "Tailnet sign-in button did not appear")
|
|
||||||
signInButton.tap()
|
|
||||||
|
|
||||||
acceptAuthenticationPromptIfNeeded(in: app, timeout: 20)
|
|
||||||
|
|
||||||
let webSession = webAuthenticationSession()
|
|
||||||
XCTAssertTrue(webSession.waitForExistence(timeout: 20), "Safari authentication session did not appear")
|
|
||||||
|
|
||||||
signIntoAuthentik(in: webSession, username: browserIdentity, password: password)
|
|
||||||
|
|
||||||
app.activate()
|
|
||||||
XCTAssertTrue(
|
|
||||||
waitForTailnetSignedIn(in: app, timeout: 60),
|
|
||||||
"Tailnet sign-in never reached the running state"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func configureTailnetIfNeeded(in app: XCUIApplication, mode: TailnetLoginMode) {
|
|
||||||
guard mode == .discovered else { return }
|
|
||||||
|
|
||||||
openTailnetMenu(in: app)
|
|
||||||
tapMenuButton(named: "Edit Custom Server", in: app)
|
|
||||||
|
|
||||||
openTailnetMenu(in: app)
|
|
||||||
tapMenuButton(named: "Show Advanced Settings", in: app)
|
|
||||||
|
|
||||||
let authorityField = app.textFields["tailnet-authority"]
|
|
||||||
XCTAssertTrue(authorityField.waitForExistence(timeout: 10), "Tailnet authority field did not appear")
|
|
||||||
replaceText(in: authorityField, with: "")
|
|
||||||
}
|
|
||||||
|
|
||||||
private func openTailnetMenu(in app: XCUIApplication) {
|
|
||||||
let moreButton = app.buttons["More"]
|
|
||||||
XCTAssertTrue(moreButton.waitForExistence(timeout: 5), "Tailnet menu button did not appear")
|
|
||||||
moreButton.tap()
|
|
||||||
}
|
|
||||||
|
|
||||||
private func tapMenuButton(named title: String, in app: XCUIApplication) {
|
|
||||||
let menuButton = firstExistingElement(
|
|
||||||
from: [
|
|
||||||
app.buttons[title],
|
|
||||||
app.descendants(matching: .button)[title],
|
|
||||||
],
|
|
||||||
timeout: 5
|
|
||||||
)
|
|
||||||
XCTAssertTrue(menuButton.exists, "Menu action \(title) did not appear")
|
|
||||||
menuButton.tap()
|
|
||||||
}
|
|
||||||
|
|
||||||
private func acceptAuthenticationPromptIfNeeded(
|
|
||||||
in app: XCUIApplication,
|
|
||||||
timeout: TimeInterval
|
|
||||||
) {
|
|
||||||
let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
|
|
||||||
let deadline = Date().addingTimeInterval(timeout)
|
|
||||||
|
|
||||||
repeat {
|
|
||||||
let promptCandidates = [
|
|
||||||
springboard.buttons["Continue"],
|
|
||||||
springboard.buttons["Allow"],
|
|
||||||
app.buttons["Continue"],
|
|
||||||
app.buttons["Allow"],
|
|
||||||
]
|
|
||||||
|
|
||||||
for button in promptCandidates where button.exists && button.isHittable {
|
|
||||||
button.tap()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
RunLoop.current.run(until: Date().addingTimeInterval(0.25))
|
|
||||||
} while Date() < deadline
|
|
||||||
|
|
||||||
let promptCandidates = [
|
|
||||||
springboard.buttons["Continue"],
|
|
||||||
springboard.buttons["Allow"],
|
|
||||||
app.buttons["Continue"],
|
|
||||||
app.buttons["Allow"],
|
|
||||||
]
|
|
||||||
|
|
||||||
for button in promptCandidates where button.exists {
|
|
||||||
button.tap()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func webAuthenticationSession() -> XCUIApplication {
|
|
||||||
let safariViewService = XCUIApplication(bundleIdentifier: "com.apple.SafariViewService")
|
|
||||||
if safariViewService.waitForExistence(timeout: 5) {
|
|
||||||
return safariViewService
|
|
||||||
}
|
|
||||||
|
|
||||||
let safari = XCUIApplication(bundleIdentifier: "com.apple.mobilesafari")
|
|
||||||
_ = safari.waitForExistence(timeout: 5)
|
|
||||||
return safari
|
|
||||||
}
|
|
||||||
|
|
||||||
private func signIntoAuthentik(in webSession: XCUIApplication, username: String, password: String) {
|
|
||||||
followTailnetRedirectIfNeeded(in: webSession)
|
|
||||||
|
|
||||||
if !webSession.exists {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let immediatePasswordField = firstExistingSecureField(in: webSession, timeout: 2)
|
|
||||||
if immediatePasswordField.exists {
|
|
||||||
replaceSecureText(in: immediatePasswordField, within: webSession, with: password)
|
|
||||||
submitAuthenticationForm(in: webSession, focusedField: immediatePasswordField)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let usernameField = firstExistingElement(
|
|
||||||
in: webSession,
|
|
||||||
queries: [
|
|
||||||
{ $0.textFields["Username"] },
|
|
||||||
{ $0.textFields["Email or Username"] },
|
|
||||||
{ $0.textFields["Email address"] },
|
|
||||||
{ $0.textFields["Email"] },
|
|
||||||
{ $0.webViews.textFields["Username"] },
|
|
||||||
{ $0.webViews.textFields["Email or Username"] },
|
|
||||||
{ $0.descendants(matching: .textField).firstMatch },
|
|
||||||
],
|
|
||||||
timeout: 12
|
|
||||||
)
|
|
||||||
if !usernameField.exists {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
replaceText(in: usernameField, with: username)
|
|
||||||
|
|
||||||
tapFirstExistingButton(
|
|
||||||
in: webSession,
|
|
||||||
titles: ["Continue", "Next", "Sign In", "Log in", "Login"],
|
|
||||||
timeout: 5
|
|
||||||
)
|
|
||||||
|
|
||||||
let passwordField = firstExistingSecureField(in: webSession, timeout: 20)
|
|
||||||
XCTAssertTrue(passwordField.exists, "Authentik password field did not appear")
|
|
||||||
replaceSecureText(in: passwordField, within: webSession, with: password)
|
|
||||||
submitAuthenticationForm(in: webSession, focusedField: passwordField)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func followTailnetRedirectIfNeeded(in webSession: XCUIApplication) {
|
|
||||||
let redirectCandidates = [
|
|
||||||
webSession.links["Found"],
|
|
||||||
webSession.webViews.links["Found"],
|
|
||||||
webSession.buttons["Found"],
|
|
||||||
webSession.webViews.buttons["Found"],
|
|
||||||
]
|
|
||||||
|
|
||||||
let redirectLink = firstExistingElement(from: redirectCandidates, timeout: 8)
|
|
||||||
if redirectLink.exists {
|
|
||||||
redirectLink.tap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func firstExistingSecureField(in app: XCUIApplication, timeout: TimeInterval) -> XCUIElement {
|
|
||||||
let candidates = [
|
|
||||||
app.descendants(matching: .secureTextField).firstMatch,
|
|
||||||
app.secureTextFields["Password"],
|
|
||||||
app.secureTextFields["Password or Token"],
|
|
||||||
app.webViews.secureTextFields["Password"],
|
|
||||||
app.webViews.secureTextFields["Password or Token"],
|
|
||||||
]
|
|
||||||
|
|
||||||
return firstExistingElement(from: candidates, timeout: timeout)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func tapFirstExistingButton(
|
|
||||||
in app: XCUIApplication,
|
|
||||||
titles: [String],
|
|
||||||
timeout: TimeInterval
|
|
||||||
) {
|
|
||||||
let candidates = titles.flatMap { title in
|
|
||||||
[
|
|
||||||
app.buttons[title],
|
|
||||||
app.webViews.buttons[title],
|
|
||||||
]
|
|
||||||
} + [app.descendants(matching: .button).firstMatch]
|
|
||||||
|
|
||||||
let button = firstExistingElement(from: candidates, timeout: timeout)
|
|
||||||
XCTAssertTrue(button.exists, "Expected one of \(titles.joined(separator: ", ")) to appear")
|
|
||||||
button.tap()
|
|
||||||
}
|
|
||||||
|
|
||||||
private func submitAuthenticationForm(in app: XCUIApplication, focusedField: XCUIElement) {
|
|
||||||
focus(focusedField)
|
|
||||||
focusedField.typeText("\n")
|
|
||||||
if waitForAny(
|
|
||||||
[
|
|
||||||
{ !focusedField.exists },
|
|
||||||
{ !app.staticTexts["Burrow Tailnet Authentication"].exists },
|
|
||||||
],
|
|
||||||
timeout: 1.5
|
|
||||||
) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let keyboard = app.keyboards.firstMatch
|
|
||||||
if keyboard.waitForExistence(timeout: 2) {
|
|
||||||
let keyboardCandidates = [
|
|
||||||
"Return",
|
|
||||||
"return",
|
|
||||||
"Go",
|
|
||||||
"go",
|
|
||||||
"Continue",
|
|
||||||
"continue",
|
|
||||||
"Done",
|
|
||||||
"done",
|
|
||||||
"Join",
|
|
||||||
"join",
|
|
||||||
"Sign In",
|
|
||||||
"Log In",
|
|
||||||
"Login",
|
|
||||||
]
|
|
||||||
for title in keyboardCandidates {
|
|
||||||
let key = keyboard.buttons[title]
|
|
||||||
if key.exists && key.isHittable {
|
|
||||||
key.tap()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let lastKey = keyboard.buttons.allElementsBoundByIndex.last,
|
|
||||||
lastKey.exists,
|
|
||||||
lastKey.isHittable
|
|
||||||
{
|
|
||||||
lastKey.tap()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tapFirstExistingButton(
|
|
||||||
in: app,
|
|
||||||
titles: ["Continue", "Sign In", "Log in", "Login"],
|
|
||||||
timeout: 5
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func loadTestConfig() throws -> TestConfig {
|
|
||||||
let environment = ProcessInfo.processInfo.environment
|
|
||||||
if let email = nonEmptyEnvironment("BURROW_UI_TEST_EMAIL"),
|
|
||||||
let password = nonEmptyEnvironment("BURROW_UI_TEST_PASSWORD")
|
|
||||||
{
|
|
||||||
return TestConfig(
|
|
||||||
email: email,
|
|
||||||
username: nonEmptyEnvironment("BURROW_UI_TEST_USERNAME") ?? email,
|
|
||||||
password: password,
|
|
||||||
mode: nonEmptyEnvironment("BURROW_UI_TEST_TAILNET_MODE")
|
|
||||||
.flatMap(TailnetLoginMode.init(rawValue:))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
let configPath = environment["BURROW_UI_TEST_CONFIG_PATH"] ?? "/tmp/burrow-ui-test-config.json"
|
|
||||||
let configURL = URL(fileURLWithPath: configPath)
|
|
||||||
guard FileManager.default.fileExists(atPath: configURL.path) else {
|
|
||||||
throw XCTSkip(
|
|
||||||
"Missing UI test configuration. Expected env vars or config file at \(configURL.path)"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
let data = try Data(contentsOf: configURL)
|
|
||||||
return try JSONDecoder().decode(TestConfig.self, from: data)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func nonEmptyEnvironment(_ key: String) -> String? {
|
|
||||||
guard let value = ProcessInfo.processInfo.environment[key]?
|
|
||||||
.trimmingCharacters(in: .whitespacesAndNewlines),
|
|
||||||
!value.isEmpty
|
|
||||||
else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
private func waitForFieldValue(
|
|
||||||
_ field: XCUIElement,
|
|
||||||
containing substring: String,
|
|
||||||
timeout: TimeInterval
|
|
||||||
) -> Bool {
|
|
||||||
let predicate = NSPredicate(format: "value CONTAINS %@", substring)
|
|
||||||
let expectation = XCTNSPredicateExpectation(predicate: predicate, object: field)
|
|
||||||
return XCTWaiter.wait(for: [expectation], timeout: timeout) == .completed
|
|
||||||
}
|
|
||||||
|
|
||||||
private func waitForButtonLabel(
|
|
||||||
_ button: XCUIElement,
|
|
||||||
equals expected: String,
|
|
||||||
timeout: TimeInterval
|
|
||||||
) -> Bool {
|
|
||||||
let predicate = NSPredicate(format: "label == %@", expected)
|
|
||||||
let expectation = XCTNSPredicateExpectation(predicate: predicate, object: button)
|
|
||||||
return XCTWaiter.wait(for: [expectation], timeout: timeout) == .completed
|
|
||||||
}
|
|
||||||
|
|
||||||
private func waitForTailnetSignedIn(in app: XCUIApplication, timeout: TimeInterval) -> Bool {
|
|
||||||
let button = app.buttons["tailnet-start-sign-in"]
|
|
||||||
let deadline = Date().addingTimeInterval(timeout)
|
|
||||||
|
|
||||||
repeat {
|
|
||||||
acceptAuthenticationPromptIfNeeded(in: app, timeout: 1)
|
|
||||||
if button.exists, button.label == "Signed In" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
RunLoop.current.run(until: Date().addingTimeInterval(0.3))
|
|
||||||
} while Date() < deadline
|
|
||||||
|
|
||||||
return button.exists && button.label == "Signed In"
|
|
||||||
}
|
|
||||||
|
|
||||||
private func waitForAny(_ conditions: [() -> Bool], timeout: TimeInterval) -> Bool {
|
|
||||||
let deadline = Date().addingTimeInterval(timeout)
|
|
||||||
repeat {
|
|
||||||
if conditions.contains(where: { $0() }) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
RunLoop.current.run(until: Date().addingTimeInterval(0.2))
|
|
||||||
} while Date() < deadline
|
|
||||||
return conditions.contains(where: { $0() })
|
|
||||||
}
|
|
||||||
|
|
||||||
private func firstExistingElement(
|
|
||||||
in app: XCUIApplication,
|
|
||||||
queries: [(XCUIApplication) -> XCUIElement],
|
|
||||||
timeout: TimeInterval
|
|
||||||
) -> XCUIElement {
|
|
||||||
firstExistingElement(from: queries.map { $0(app) }, timeout: timeout)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func firstExistingElement(from candidates: [XCUIElement], timeout: TimeInterval) -> XCUIElement {
|
|
||||||
let deadline = Date().addingTimeInterval(timeout)
|
|
||||||
repeat {
|
|
||||||
for candidate in candidates where candidate.exists {
|
|
||||||
return candidate
|
|
||||||
}
|
|
||||||
RunLoop.current.run(until: Date().addingTimeInterval(0.2))
|
|
||||||
} while Date() < deadline
|
|
||||||
|
|
||||||
return candidates[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
private func replaceText(in element: XCUIElement, with value: String) {
|
|
||||||
focus(element)
|
|
||||||
clearText(in: element)
|
|
||||||
element.typeText(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func replaceSecureText(in element: XCUIElement, within app: XCUIApplication, with value: String) {
|
|
||||||
UIPasteboard.general.string = value
|
|
||||||
focus(element)
|
|
||||||
for revealMenu in [
|
|
||||||
{ element.doubleTap() },
|
|
||||||
{ element.press(forDuration: 1.2) },
|
|
||||||
] {
|
|
||||||
revealMenu()
|
|
||||||
let pasteButton = firstExistingElement(from: pasteCandidates(in: app), timeout: 3)
|
|
||||||
if pasteButton.exists {
|
|
||||||
pasteButton.tap()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
focus(element)
|
|
||||||
element.typeText(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func clearText(in element: XCUIElement) {
|
|
||||||
guard let currentValue = element.value as? String, !currentValue.isEmpty else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let deleteSequence = String(repeating: XCUIKeyboardKey.delete.rawValue, count: currentValue.count)
|
|
||||||
element.typeText(deleteSequence)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func focus(_ element: XCUIElement) {
|
|
||||||
element.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap()
|
|
||||||
RunLoop.current.run(until: Date().addingTimeInterval(0.3))
|
|
||||||
}
|
|
||||||
|
|
||||||
private func pasteCandidates(in app: XCUIApplication) -> [XCUIElement] {
|
|
||||||
let pasteLabels = ["Paste", "Incolla", "Paste from Clipboard"]
|
|
||||||
return pasteLabels.flatMap { label in
|
|
||||||
[
|
|
||||||
app.menuItems[label],
|
|
||||||
app.buttons[label],
|
|
||||||
app.webViews.buttons[label],
|
|
||||||
app.descendants(matching: .button).matching(NSPredicate(format: "label == %@", label)).firstMatch,
|
|
||||||
app.descendants(matching: .menuItem).matching(NSPredicate(format: "label == %@", label)).firstMatch,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -7,59 +7,14 @@
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
D00AA8972A4669BC005C8102 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00AA8962A4669BC005C8102 /* AppDelegate.swift */; };
|
|
||||||
D11000012F70000100112233 /* BurrowUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D11000042F70000100112233 /* BurrowUITests.swift */; };
|
|
||||||
D020F65829E4A697002790F6 /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = D020F65729E4A697002790F6 /* PacketTunnelProvider.swift */; };
|
D020F65829E4A697002790F6 /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = D020F65729E4A697002790F6 /* PacketTunnelProvider.swift */; };
|
||||||
D020F65D29E4A697002790F6 /* BurrowNetworkExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = D020F65329E4A697002790F6 /* BurrowNetworkExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
D020F65D29E4A697002790F6 /* BurrowNetworkExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = D020F65329E4A697002790F6 /* BurrowNetworkExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
D03383AD2C8E67E300F7C44E /* SwiftProtobuf in Frameworks */ = {isa = PBXBuildFile; productRef = D078F7E22C8DA375008A8CEC /* SwiftProtobuf */; };
|
|
||||||
D03383AE2C8E67E300F7C44E /* NIO in Frameworks */ = {isa = PBXBuildFile; productRef = D044EE902C8DAB2000778185 /* NIO */; };
|
|
||||||
D03383AF2C8E67E300F7C44E /* NIOConcurrencyHelpers in Frameworks */ = {isa = PBXBuildFile; productRef = D044EE922C8DAB2000778185 /* NIOConcurrencyHelpers */; };
|
|
||||||
D03383B02C8E67E300F7C44E /* NIOTransportServices in Frameworks */ = {isa = PBXBuildFile; productRef = D044EE952C8DAB2800778185 /* NIOTransportServices */; };
|
|
||||||
D05B9F7629E39EEC008CB1F9 /* BurrowApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05B9F7529E39EEC008CB1F9 /* BurrowApp.swift */; };
|
D05B9F7629E39EEC008CB1F9 /* BurrowApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05B9F7529E39EEC008CB1F9 /* BurrowApp.swift */; };
|
||||||
D09150422B9D2AF700BE3CB0 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = D09150412B9D2AF700BE3CB0 /* MainMenu.xib */; platformFilters = (macos, ); };
|
D05B9F7829E39EEC008CB1F9 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05B9F7729E39EEC008CB1F9 /* ContentView.swift */; };
|
||||||
D0A11C102F90000100112233 /* DequeModule in Frameworks */ = {isa = PBXBuildFile; productRef = D0A11C0F2F90000100112233 /* DequeModule */; };
|
D05B9F7A29E39EED008CB1F9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D05B9F7929E39EED008CB1F9 /* Assets.xcassets */; };
|
||||||
D0B1D1102C436152004B7823 /* AsyncAlgorithms in Frameworks */ = {isa = PBXBuildFile; productRef = D0B1D10F2C436152004B7823 /* AsyncAlgorithms */; };
|
|
||||||
D0BCC6092A09A03E00AD070D /* libburrow.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D0BCC6032A09535900AD070D /* libburrow.a */; };
|
|
||||||
D0BF09522C8E66F6000D8DEC /* BurrowConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0D4E5622C8D9BF4007F820A /* BurrowConfiguration.framework */; };
|
|
||||||
D0BF09552C8E66FD000D8DEC /* BurrowConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0D4E5622C8D9BF4007F820A /* BurrowConfiguration.framework */; };
|
|
||||||
D0D4E53A2C8D996F007F820A /* BurrowCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D0D4E5312C8D996F007F820A /* BurrowCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
|
||||||
D0D4E56B2C8D9C2F007F820A /* Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E49A2C8D921A007F820A /* Logging.swift */; };
|
|
||||||
D0D4E5702C8D9C62007F820A /* BurrowCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0D4E5312C8D996F007F820A /* BurrowCore.framework */; };
|
|
||||||
D0D4E5722C8D9C6F007F820A /* Network.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E49E2C8D921A007F820A /* Network.swift */; };
|
|
||||||
D0D4E5732C8D9C6F007F820A /* WireGuard.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E49F2C8D921A007F820A /* WireGuard.swift */; };
|
|
||||||
D0D4E5742C8D9C6F007F820A /* BurrowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E4A22C8D921A007F820A /* BurrowView.swift */; };
|
|
||||||
D0D4E5752C8D9C6F007F820A /* FloatingButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E4A32C8D921A007F820A /* FloatingButtonStyle.swift */; };
|
|
||||||
D0D4E5762C8D9C6F007F820A /* MenuItemToggleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E4A42C8D921A007F820A /* MenuItemToggleView.swift */; };
|
|
||||||
D0D4E5772C8D9C6F007F820A /* NetworkCarouselView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E4A52C8D921A007F820A /* NetworkCarouselView.swift */; };
|
|
||||||
D0D4E5782C8D9C6F007F820A /* NetworkExtension+Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E4A62C8D921A007F820A /* NetworkExtension+Async.swift */; };
|
|
||||||
D0D4E5792C8D9C6F007F820A /* NetworkExtensionTunnel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E4A72C8D921A007F820A /* NetworkExtensionTunnel.swift */; };
|
|
||||||
D0D4E57A2C8D9C6F007F820A /* NetworkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E4A82C8D921A007F820A /* NetworkView.swift */; };
|
|
||||||
D0D4E57C2C8D9C6F007F820A /* Tunnel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E4AA2C8D921A007F820A /* Tunnel.swift */; };
|
|
||||||
D0D4E57D2C8D9C6F007F820A /* TunnelButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E4AB2C8D921A007F820A /* TunnelButton.swift */; };
|
|
||||||
D0D4E57E2C8D9C6F007F820A /* TunnelStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E4AC2C8D921A007F820A /* TunnelStatusView.swift */; };
|
|
||||||
D0D4E5812C8D9C94007F820A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D0D4E4A12C8D921A007F820A /* Assets.xcassets */; };
|
|
||||||
D0D4E5892C8D9C94007F820A /* BurrowUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0D4E5582C8D9BF2007F820A /* BurrowUI.framework */; };
|
|
||||||
D0D4E58A2C8D9C9E007F820A /* BurrowUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D0D4E5582C8D9BF2007F820A /* BurrowUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
|
||||||
D0D4E58B2C8D9CA4007F820A /* BurrowConfiguration.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D0D4E5622C8D9BF4007F820A /* BurrowConfiguration.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
|
||||||
D0D4E5922C8D9D15007F820A /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E58F2C8D9D0A007F820A /* Constants.swift */; };
|
|
||||||
D0D4E5A62C8D9E65007F820A /* BurrowCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0D4E5312C8D996F007F820A /* BurrowCore.framework */; };
|
|
||||||
D0F4FAD32C8DC79C0068730A /* BurrowCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0D4E5312C8D996F007F820A /* BurrowCore.framework */; };
|
|
||||||
D0F7594E2C8DAB6B00126CF3 /* GRPC in Frameworks */ = {isa = PBXBuildFile; productRef = D078F7E02C8DA375008A8CEC /* GRPC */; };
|
|
||||||
D0FA10012D10200100112233 /* burrow.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FA10032D10200100112233 /* burrow.pb.swift */; };
|
|
||||||
D0FA10022D10200100112233 /* burrow.grpc.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FA10042D10200100112233 /* burrow.grpc.swift */; };
|
|
||||||
D0F7597E2C8DB30500126CF3 /* CGRPCZlib in Frameworks */ = {isa = PBXBuildFile; productRef = D0F7597D2C8DB30500126CF3 /* CGRPCZlib */; };
|
|
||||||
D0F7598D2C8DB3DA00126CF3 /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D4E4992C8D921A007F820A /* Client.swift */; };
|
|
||||||
D0C0DE102FA0000100112233 /* Sparkle in Frameworks */ = {isa = PBXBuildFile; platformFilters = (macos, ); productRef = D0C0DE122FA0000100112233 /* Sparkle */; };
|
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
D11000022F70000100112233 /* PBXContainerItemProxy */ = {
|
|
||||||
isa = PBXContainerItemProxy;
|
|
||||||
containerPortal = D05B9F6A29E39EEC008CB1F9 /* Project object */;
|
|
||||||
proxyType = 1;
|
|
||||||
remoteGlobalIDString = D05B9F7129E39EEC008CB1F9;
|
|
||||||
remoteInfo = App;
|
|
||||||
};
|
|
||||||
D020F65B29E4A697002790F6 /* PBXContainerItemProxy */ = {
|
D020F65B29E4A697002790F6 /* PBXContainerItemProxy */ = {
|
||||||
isa = PBXContainerItemProxy;
|
isa = PBXContainerItemProxy;
|
||||||
containerPortal = D05B9F6A29E39EEC008CB1F9 /* Project object */;
|
containerPortal = D05B9F6A29E39EEC008CB1F9 /* Project object */;
|
||||||
|
|
@ -67,48 +22,6 @@
|
||||||
remoteGlobalIDString = D020F65229E4A697002790F6;
|
remoteGlobalIDString = D020F65229E4A697002790F6;
|
||||||
remoteInfo = BurrowNetworkExtension;
|
remoteInfo = BurrowNetworkExtension;
|
||||||
};
|
};
|
||||||
D0BF09502C8E66F1000D8DEC /* PBXContainerItemProxy */ = {
|
|
||||||
isa = PBXContainerItemProxy;
|
|
||||||
containerPortal = D05B9F6A29E39EEC008CB1F9 /* Project object */;
|
|
||||||
proxyType = 1;
|
|
||||||
remoteGlobalIDString = D0D4E55A2C8D9BF4007F820A;
|
|
||||||
remoteInfo = Configuration;
|
|
||||||
};
|
|
||||||
D0BF09532C8E66FA000D8DEC /* PBXContainerItemProxy */ = {
|
|
||||||
isa = PBXContainerItemProxy;
|
|
||||||
containerPortal = D05B9F6A29E39EEC008CB1F9 /* Project object */;
|
|
||||||
proxyType = 1;
|
|
||||||
remoteGlobalIDString = D0D4E55A2C8D9BF4007F820A;
|
|
||||||
remoteInfo = Configuration;
|
|
||||||
};
|
|
||||||
D0D4E56E2C8D9C5D007F820A /* PBXContainerItemProxy */ = {
|
|
||||||
isa = PBXContainerItemProxy;
|
|
||||||
containerPortal = D05B9F6A29E39EEC008CB1F9 /* Project object */;
|
|
||||||
proxyType = 1;
|
|
||||||
remoteGlobalIDString = D0D4E5302C8D996F007F820A;
|
|
||||||
remoteInfo = Core;
|
|
||||||
};
|
|
||||||
D0D4E57F2C8D9C78007F820A /* PBXContainerItemProxy */ = {
|
|
||||||
isa = PBXContainerItemProxy;
|
|
||||||
containerPortal = D05B9F6A29E39EEC008CB1F9 /* Project object */;
|
|
||||||
proxyType = 1;
|
|
||||||
remoteGlobalIDString = D0D4E5302C8D996F007F820A;
|
|
||||||
remoteInfo = Core;
|
|
||||||
};
|
|
||||||
D0D4E5872C8D9C88007F820A /* PBXContainerItemProxy */ = {
|
|
||||||
isa = PBXContainerItemProxy;
|
|
||||||
containerPortal = D05B9F6A29E39EEC008CB1F9 /* Project object */;
|
|
||||||
proxyType = 1;
|
|
||||||
remoteGlobalIDString = D0D4E5502C8D9BF2007F820A;
|
|
||||||
remoteInfo = UI;
|
|
||||||
};
|
|
||||||
D0F4FAD12C8DC7960068730A /* PBXContainerItemProxy */ = {
|
|
||||||
isa = PBXContainerItemProxy;
|
|
||||||
containerPortal = D05B9F6A29E39EEC008CB1F9 /* Project object */;
|
|
||||||
proxyType = 1;
|
|
||||||
remoteGlobalIDString = D0D4E5302C8D996F007F820A;
|
|
||||||
remoteInfo = Core;
|
|
||||||
};
|
|
||||||
/* End PBXContainerItemProxy section */
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
/* Begin PBXCopyFilesBuildPhase section */
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
|
|
@ -123,31 +36,13 @@
|
||||||
name = "Embed Foundation Extensions";
|
name = "Embed Foundation Extensions";
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
D0D4E53F2C8D996F007F820A /* Embed Frameworks */ = {
|
|
||||||
isa = PBXCopyFilesBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
dstPath = "";
|
|
||||||
dstSubfolderSpec = 10;
|
|
||||||
files = (
|
|
||||||
D0D4E58B2C8D9CA4007F820A /* BurrowConfiguration.framework in Embed Frameworks */,
|
|
||||||
D0D4E58A2C8D9C9E007F820A /* BurrowUI.framework in Embed Frameworks */,
|
|
||||||
D0D4E53A2C8D996F007F820A /* BurrowCore.framework in Embed Frameworks */,
|
|
||||||
);
|
|
||||||
name = "Embed Frameworks";
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
/* End PBXCopyFilesBuildPhase section */
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
D00117422B30348D00D87C25 /* Configuration.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Configuration.xcconfig; sourceTree = "<group>"; };
|
|
||||||
D00AA8962A4669BC005C8102 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
|
||||||
D11000032F70000100112233 /* BurrowUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BurrowUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
||||||
D11000042F70000100112233 /* BurrowUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BurrowUITests.swift; sourceTree = "<group>"; };
|
|
||||||
D11000052F70000100112233 /* UITests.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = UITests.xcconfig; sourceTree = "<group>"; };
|
|
||||||
D020F63D29E4A1FF002790F6 /* Identity.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Identity.xcconfig; sourceTree = "<group>"; };
|
D020F63D29E4A1FF002790F6 /* Identity.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Identity.xcconfig; sourceTree = "<group>"; };
|
||||||
D020F64029E4A1FF002790F6 /* Compiler.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Compiler.xcconfig; sourceTree = "<group>"; };
|
D020F64029E4A1FF002790F6 /* Compiler.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Compiler.xcconfig; sourceTree = "<group>"; };
|
||||||
D020F64229E4A1FF002790F6 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
D020F64229E4A1FF002790F6 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
D020F64929E4A34B002790F6 /* App.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = App.xcconfig; sourceTree = "<group>"; };
|
D020F64929E4A34B002790F6 /* Burrow.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Burrow.xcconfig; sourceTree = "<group>"; };
|
||||||
D020F64A29E4A452002790F6 /* App.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = App.xcconfig; sourceTree = "<group>"; };
|
D020F64A29E4A452002790F6 /* App.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = App.xcconfig; sourceTree = "<group>"; };
|
||||||
D020F65329E4A697002790F6 /* BurrowNetworkExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = BurrowNetworkExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
D020F65329E4A697002790F6 /* BurrowNetworkExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = BurrowNetworkExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
D020F65729E4A697002790F6 /* PacketTunnelProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PacketTunnelProvider.swift; sourceTree = "<group>"; };
|
D020F65729E4A697002790F6 /* PacketTunnelProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PacketTunnelProvider.swift; sourceTree = "<group>"; };
|
||||||
|
|
@ -158,59 +53,17 @@
|
||||||
D020F66729E4A95D002790F6 /* NetworkExtension-iOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "NetworkExtension-iOS.entitlements"; sourceTree = "<group>"; };
|
D020F66729E4A95D002790F6 /* NetworkExtension-iOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "NetworkExtension-iOS.entitlements"; sourceTree = "<group>"; };
|
||||||
D020F66829E4AA74002790F6 /* App-iOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "App-iOS.entitlements"; sourceTree = "<group>"; };
|
D020F66829E4AA74002790F6 /* App-iOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "App-iOS.entitlements"; sourceTree = "<group>"; };
|
||||||
D020F66929E4AA74002790F6 /* App-macOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "App-macOS.entitlements"; sourceTree = "<group>"; };
|
D020F66929E4AA74002790F6 /* App-macOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "App-macOS.entitlements"; sourceTree = "<group>"; };
|
||||||
D04A3E1D2BAF465F0043EC85 /* Version.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Version.xcconfig; sourceTree = "<group>"; };
|
|
||||||
D05B9F7229E39EEC008CB1F9 /* Burrow.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Burrow.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
D05B9F7229E39EEC008CB1F9 /* Burrow.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Burrow.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
D05B9F7529E39EEC008CB1F9 /* BurrowApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BurrowApp.swift; sourceTree = "<group>"; };
|
D05B9F7529E39EEC008CB1F9 /* BurrowApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BurrowApp.swift; sourceTree = "<group>"; };
|
||||||
D09150412B9D2AF700BE3CB0 /* MainMenu.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = "<group>"; };
|
D05B9F7729E39EEC008CB1F9 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||||
D0B98FBF29FD8072004E7149 /* build-rust.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "build-rust.sh"; sourceTree = "<group>"; };
|
D05B9F7929E39EED008CB1F9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
D0B98FD829FDDB6F004E7149 /* libburrow.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = libburrow.h; sourceTree = "<group>"; };
|
|
||||||
D0B98FDC29FDDDCF004E7149 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
|
|
||||||
D0BCC6032A09535900AD070D /* libburrow.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libburrow.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
||||||
D0BF09582C8E6789000D8DEC /* UI.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = UI.xcconfig; sourceTree = "<group>"; };
|
|
||||||
D0D4E4952C8D921A007F820A /* burrow.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = burrow.proto; sourceTree = "<group>"; };
|
|
||||||
D0D4E4992C8D921A007F820A /* Client.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Client.swift; sourceTree = "<group>"; };
|
|
||||||
D0D4E49A2C8D921A007F820A /* Logging.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logging.swift; sourceTree = "<group>"; };
|
|
||||||
D0D4E49E2C8D921A007F820A /* Network.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Network.swift; sourceTree = "<group>"; };
|
|
||||||
D0D4E49F2C8D921A007F820A /* WireGuard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WireGuard.swift; sourceTree = "<group>"; };
|
|
||||||
D0D4E4A12C8D921A007F820A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
|
||||||
D0D4E4A22C8D921A007F820A /* BurrowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BurrowView.swift; sourceTree = "<group>"; };
|
|
||||||
D0D4E4A32C8D921A007F820A /* FloatingButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatingButtonStyle.swift; sourceTree = "<group>"; };
|
|
||||||
D0D4E4A42C8D921A007F820A /* MenuItemToggleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuItemToggleView.swift; sourceTree = "<group>"; };
|
|
||||||
D0D4E4A52C8D921A007F820A /* NetworkCarouselView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkCarouselView.swift; sourceTree = "<group>"; };
|
|
||||||
D0D4E4A62C8D921A007F820A /* NetworkExtension+Async.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NetworkExtension+Async.swift"; sourceTree = "<group>"; };
|
|
||||||
D0D4E4A72C8D921A007F820A /* NetworkExtensionTunnel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkExtensionTunnel.swift; sourceTree = "<group>"; };
|
|
||||||
D0D4E4A82C8D921A007F820A /* NetworkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkView.swift; sourceTree = "<group>"; };
|
|
||||||
D0D4E4AA2C8D921A007F820A /* Tunnel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tunnel.swift; sourceTree = "<group>"; };
|
|
||||||
D0D4E4AB2C8D921A007F820A /* TunnelButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelButton.swift; sourceTree = "<group>"; };
|
|
||||||
D0D4E4AC2C8D921A007F820A /* TunnelStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelStatusView.swift; sourceTree = "<group>"; };
|
|
||||||
D0D4E4F62C8D932D007F820A /* Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
|
|
||||||
D0D4E4F72C8D941D007F820A /* Framework.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Framework.xcconfig; sourceTree = "<group>"; };
|
|
||||||
D0D4E5312C8D996F007F820A /* BurrowCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BurrowCore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
||||||
D0D4E5582C8D9BF2007F820A /* BurrowUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BurrowUI.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
||||||
D0D4E5622C8D9BF4007F820A /* BurrowConfiguration.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BurrowConfiguration.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
||||||
D0D4E58E2C8D9D0A007F820A /* Constants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Constants.h; sourceTree = "<group>"; };
|
|
||||||
D0D4E58F2C8D9D0A007F820A /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
|
|
||||||
D0D4E5902C8D9D0A007F820A /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
|
|
||||||
D0FA10032D10200100112233 /* burrow.pb.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Generated/burrow.pb.swift; sourceTree = "<group>"; };
|
|
||||||
D0FA10042D10200100112233 /* burrow.grpc.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Generated/burrow.grpc.swift; sourceTree = "<group>"; };
|
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
D11000062F70000100112233 /* Frameworks */ = {
|
|
||||||
isa = PBXFrameworksBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
D020F65029E4A697002790F6 /* Frameworks */ = {
|
D020F65029E4A697002790F6 /* Frameworks */ = {
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
D0BF09522C8E66F6000D8DEC /* BurrowConfiguration.framework in Frameworks */,
|
|
||||||
D0D4E5A62C8D9E65007F820A /* BurrowCore.framework in Frameworks */,
|
|
||||||
D0BCC6092A09A03E00AD070D /* libburrow.a in Frameworks */,
|
|
||||||
D0B1D1102C436152004B7823 /* AsyncAlgorithms in Frameworks */,
|
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
@ -218,59 +71,20 @@
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
D0BF09552C8E66FD000D8DEC /* BurrowConfiguration.framework in Frameworks */,
|
|
||||||
D0F4FAD32C8DC79C0068730A /* BurrowCore.framework in Frameworks */,
|
|
||||||
D0D4E5892C8D9C94007F820A /* BurrowUI.framework in Frameworks */,
|
|
||||||
D0C0DE102FA0000100112233 /* Sparkle in Frameworks */,
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
D078F7CF2C8DA213008A8CEC /* Frameworks */ = {
|
|
||||||
isa = PBXFrameworksBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
D03383B02C8E67E300F7C44E /* NIOTransportServices in Frameworks */,
|
|
||||||
D03383AF2C8E67E300F7C44E /* NIOConcurrencyHelpers in Frameworks */,
|
|
||||||
D03383AE2C8E67E300F7C44E /* NIO in Frameworks */,
|
|
||||||
D03383AD2C8E67E300F7C44E /* SwiftProtobuf in Frameworks */,
|
|
||||||
D0F7594E2C8DAB6B00126CF3 /* GRPC in Frameworks */,
|
|
||||||
D0F7597E2C8DB30500126CF3 /* CGRPCZlib in Frameworks */,
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
D0D4E5532C8D9BF2007F820A /* Frameworks */ = {
|
|
||||||
isa = PBXFrameworksBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
D0A11C102F90000100112233 /* DequeModule in Frameworks */,
|
|
||||||
D0D4E5702C8D9C62007F820A /* BurrowCore.framework in Frameworks */,
|
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
D00117432B30372900D87C25 /* Frameworks */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
);
|
|
||||||
name = Frameworks;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
D020F63C29E4A1FF002790F6 /* Configuration */ = {
|
D020F63C29E4A1FF002790F6 /* Configuration */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
D020F63D29E4A1FF002790F6 /* Identity.xcconfig */,
|
D020F63D29E4A1FF002790F6 /* Identity.xcconfig */,
|
||||||
D020F64A29E4A452002790F6 /* App.xcconfig */,
|
D020F64A29E4A452002790F6 /* App.xcconfig */,
|
||||||
D020F66329E4A703002790F6 /* Extension.xcconfig */,
|
D020F66329E4A703002790F6 /* Extension.xcconfig */,
|
||||||
D0D4E4F72C8D941D007F820A /* Framework.xcconfig */,
|
|
||||||
D020F64029E4A1FF002790F6 /* Compiler.xcconfig */,
|
D020F64029E4A1FF002790F6 /* Compiler.xcconfig */,
|
||||||
D0D4E4F62C8D932D007F820A /* Debug.xcconfig */,
|
|
||||||
D11000052F70000100112233 /* UITests.xcconfig */,
|
|
||||||
D04A3E1D2BAF465F0043EC85 /* Version.xcconfig */,
|
|
||||||
D020F64229E4A1FF002790F6 /* Info.plist */,
|
D020F64229E4A1FF002790F6 /* Info.plist */,
|
||||||
D0D4E5912C8D9D0A007F820A /* Constants */,
|
|
||||||
D00117422B30348D00D87C25 /* Configuration.xcconfig */,
|
|
||||||
);
|
);
|
||||||
path = Configuration;
|
path = Configuration;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -283,7 +97,6 @@
|
||||||
D020F66729E4A95D002790F6 /* NetworkExtension-iOS.entitlements */,
|
D020F66729E4A95D002790F6 /* NetworkExtension-iOS.entitlements */,
|
||||||
D020F66629E4A95D002790F6 /* NetworkExtension-macOS.entitlements */,
|
D020F66629E4A95D002790F6 /* NetworkExtension-macOS.entitlements */,
|
||||||
D020F66229E4A6E5002790F6 /* NetworkExtension.xcconfig */,
|
D020F66229E4A6E5002790F6 /* NetworkExtension.xcconfig */,
|
||||||
D0B98FD729FDDB57004E7149 /* libburrow */,
|
|
||||||
);
|
);
|
||||||
path = NetworkExtension;
|
path = NetworkExtension;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -292,13 +105,9 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
D05B9F7429E39EEC008CB1F9 /* App */,
|
D05B9F7429E39EEC008CB1F9 /* App */,
|
||||||
D11000072F70000100112233 /* AppUITests */,
|
|
||||||
D020F65629E4A697002790F6 /* NetworkExtension */,
|
D020F65629E4A697002790F6 /* NetworkExtension */,
|
||||||
D0D4E49C2C8D921A007F820A /* Core */,
|
|
||||||
D0D4E4AD2C8D921A007F820A /* UI */,
|
|
||||||
D020F63C29E4A1FF002790F6 /* Configuration */,
|
D020F63C29E4A1FF002790F6 /* Configuration */,
|
||||||
D05B9F7329E39EEC008CB1F9 /* Products */,
|
D05B9F7329E39EEC008CB1F9 /* Products */,
|
||||||
D00117432B30372900D87C25 /* Frameworks */,
|
|
||||||
);
|
);
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
|
@ -306,12 +115,7 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
D05B9F7229E39EEC008CB1F9 /* Burrow.app */,
|
D05B9F7229E39EEC008CB1F9 /* Burrow.app */,
|
||||||
D11000032F70000100112233 /* BurrowUITests.xctest */,
|
|
||||||
D020F65329E4A697002790F6 /* BurrowNetworkExtension.appex */,
|
D020F65329E4A697002790F6 /* BurrowNetworkExtension.appex */,
|
||||||
D0BCC6032A09535900AD070D /* libburrow.a */,
|
|
||||||
D0D4E5312C8D996F007F820A /* BurrowCore.framework */,
|
|
||||||
D0D4E5582C8D9BF2007F820A /* BurrowUI.framework */,
|
|
||||||
D0D4E5622C8D9BF4007F820A /* BurrowConfiguration.framework */,
|
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -320,222 +124,54 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
D05B9F7529E39EEC008CB1F9 /* BurrowApp.swift */,
|
D05B9F7529E39EEC008CB1F9 /* BurrowApp.swift */,
|
||||||
D00AA8962A4669BC005C8102 /* AppDelegate.swift */,
|
D05B9F7729E39EEC008CB1F9 /* ContentView.swift */,
|
||||||
D09150412B9D2AF700BE3CB0 /* MainMenu.xib */,
|
D05B9F7929E39EED008CB1F9 /* Assets.xcassets */,
|
||||||
D020F66829E4AA74002790F6 /* App-iOS.entitlements */,
|
D020F66829E4AA74002790F6 /* App-iOS.entitlements */,
|
||||||
D020F66929E4AA74002790F6 /* App-macOS.entitlements */,
|
D020F66929E4AA74002790F6 /* App-macOS.entitlements */,
|
||||||
D020F64929E4A34B002790F6 /* App.xcconfig */,
|
D020F64929E4A34B002790F6 /* Burrow.xcconfig */,
|
||||||
);
|
);
|
||||||
path = App;
|
path = App;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
D11000072F70000100112233 /* AppUITests */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
D11000042F70000100112233 /* BurrowUITests.swift */,
|
|
||||||
);
|
|
||||||
path = AppUITests;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
D0B98FD729FDDB57004E7149 /* libburrow */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
D0B98FBF29FD8072004E7149 /* build-rust.sh */,
|
|
||||||
D0B98FDC29FDDDCF004E7149 /* module.modulemap */,
|
|
||||||
D0B98FD829FDDB6F004E7149 /* libburrow.h */,
|
|
||||||
);
|
|
||||||
path = libburrow;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
D0D4E4982C8D921A007F820A /* Client */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
D0D4E4952C8D921A007F820A /* burrow.proto */,
|
|
||||||
D0FA10032D10200100112233 /* burrow.pb.swift */,
|
|
||||||
D0FA10042D10200100112233 /* burrow.grpc.swift */,
|
|
||||||
);
|
|
||||||
path = Client;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
D0D4E49C2C8D921A007F820A /* Core */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
D0D4E49A2C8D921A007F820A /* Logging.swift */,
|
|
||||||
D0D4E4992C8D921A007F820A /* Client.swift */,
|
|
||||||
D0D4E4982C8D921A007F820A /* Client */,
|
|
||||||
);
|
|
||||||
path = Core;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
D0D4E4A02C8D921A007F820A /* Networks */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
D0D4E49E2C8D921A007F820A /* Network.swift */,
|
|
||||||
D0D4E49F2C8D921A007F820A /* WireGuard.swift */,
|
|
||||||
);
|
|
||||||
path = Networks;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
D0D4E4AD2C8D921A007F820A /* UI */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
D0D4E4A22C8D921A007F820A /* BurrowView.swift */,
|
|
||||||
D0D4E4A02C8D921A007F820A /* Networks */,
|
|
||||||
D0D4E4A32C8D921A007F820A /* FloatingButtonStyle.swift */,
|
|
||||||
D0D4E4A42C8D921A007F820A /* MenuItemToggleView.swift */,
|
|
||||||
D0D4E4A52C8D921A007F820A /* NetworkCarouselView.swift */,
|
|
||||||
D0D4E4A62C8D921A007F820A /* NetworkExtension+Async.swift */,
|
|
||||||
D0D4E4A72C8D921A007F820A /* NetworkExtensionTunnel.swift */,
|
|
||||||
D0D4E4A82C8D921A007F820A /* NetworkView.swift */,
|
|
||||||
D0D4E4AA2C8D921A007F820A /* Tunnel.swift */,
|
|
||||||
D0D4E4AB2C8D921A007F820A /* TunnelButton.swift */,
|
|
||||||
D0D4E4AC2C8D921A007F820A /* TunnelStatusView.swift */,
|
|
||||||
D0D4E4A12C8D921A007F820A /* Assets.xcassets */,
|
|
||||||
D0BF09582C8E6789000D8DEC /* UI.xcconfig */,
|
|
||||||
);
|
|
||||||
path = UI;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
D0D4E5912C8D9D0A007F820A /* Constants */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
D0D4E58E2C8D9D0A007F820A /* Constants.h */,
|
|
||||||
D0D4E58F2C8D9D0A007F820A /* Constants.swift */,
|
|
||||||
D0D4E5902C8D9D0A007F820A /* module.modulemap */,
|
|
||||||
);
|
|
||||||
path = Constants;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
D11000082F70000100112233 /* BurrowUITests */ = {
|
|
||||||
isa = PBXNativeTarget;
|
|
||||||
buildConfigurationList = D110000E2F70000100112233 /* Build configuration list for PBXNativeTarget "BurrowUITests" */;
|
|
||||||
buildPhases = (
|
|
||||||
D110000A2F70000100112233 /* Sources */,
|
|
||||||
D11000062F70000100112233 /* Frameworks */,
|
|
||||||
D11000092F70000100112233 /* Resources */,
|
|
||||||
);
|
|
||||||
buildRules = (
|
|
||||||
);
|
|
||||||
dependencies = (
|
|
||||||
D110000B2F70000100112233 /* PBXTargetDependency */,
|
|
||||||
);
|
|
||||||
name = BurrowUITests;
|
|
||||||
productName = BurrowUITests;
|
|
||||||
productReference = D11000032F70000100112233 /* BurrowUITests.xctest */;
|
|
||||||
productType = "com.apple.product-type.bundle.ui-testing";
|
|
||||||
};
|
|
||||||
D020F65229E4A697002790F6 /* NetworkExtension */ = {
|
D020F65229E4A697002790F6 /* NetworkExtension */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = D020F65E29E4A697002790F6 /* Build configuration list for PBXNativeTarget "NetworkExtension" */;
|
buildConfigurationList = D020F65E29E4A697002790F6 /* Build configuration list for PBXNativeTarget "NetworkExtension" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
D0BCC60B2A09A0C100AD070D /* Compile Rust */,
|
|
||||||
D020F64F29E4A697002790F6 /* Sources */,
|
D020F64F29E4A697002790F6 /* Sources */,
|
||||||
D020F65029E4A697002790F6 /* Frameworks */,
|
D020F65029E4A697002790F6 /* Frameworks */,
|
||||||
|
D020F65129E4A697002790F6 /* Resources */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
dependencies = (
|
dependencies = (
|
||||||
D0BF09512C8E66F1000D8DEC /* PBXTargetDependency */,
|
|
||||||
D0D4E5802C8D9C78007F820A /* PBXTargetDependency */,
|
|
||||||
);
|
);
|
||||||
name = NetworkExtension;
|
name = NetworkExtension;
|
||||||
productName = BurrowNetworkExtension;
|
productName = BurrowNetworkExtension;
|
||||||
productReference = D020F65329E4A697002790F6 /* BurrowNetworkExtension.appex */;
|
productReference = D020F65329E4A697002790F6 /* BurrowNetworkExtension.appex */;
|
||||||
productType = "com.apple.product-type.app-extension";
|
productType = "com.apple.product-type.app-extension";
|
||||||
};
|
};
|
||||||
D05B9F7129E39EEC008CB1F9 /* App */ = {
|
D05B9F7129E39EEC008CB1F9 /* Burrow */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = D05B9F8129E39EED008CB1F9 /* Build configuration list for PBXNativeTarget "App" */;
|
buildConfigurationList = D05B9F8129E39EED008CB1F9 /* Build configuration list for PBXNativeTarget "Burrow" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
D05B9F6E29E39EEC008CB1F9 /* Sources */,
|
D05B9F6E29E39EEC008CB1F9 /* Sources */,
|
||||||
D05B9F6F29E39EEC008CB1F9 /* Frameworks */,
|
D05B9F6F29E39EEC008CB1F9 /* Frameworks */,
|
||||||
D05B9F7029E39EEC008CB1F9 /* Resources */,
|
D05B9F7029E39EEC008CB1F9 /* Resources */,
|
||||||
D0D4E53F2C8D996F007F820A /* Embed Frameworks */,
|
|
||||||
D020F66129E4A697002790F6 /* Embed Foundation Extensions */,
|
D020F66129E4A697002790F6 /* Embed Foundation Extensions */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
dependencies = (
|
dependencies = (
|
||||||
D0BF09542C8E66FA000D8DEC /* PBXTargetDependency */,
|
|
||||||
D0F4FAD22C8DC7960068730A /* PBXTargetDependency */,
|
|
||||||
D0D4E5882C8D9C88007F820A /* PBXTargetDependency */,
|
|
||||||
D020F65C29E4A697002790F6 /* PBXTargetDependency */,
|
D020F65C29E4A697002790F6 /* PBXTargetDependency */,
|
||||||
);
|
);
|
||||||
name = App;
|
name = Burrow;
|
||||||
packageProductDependencies = (
|
|
||||||
D0C0DE122FA0000100112233 /* Sparkle */,
|
|
||||||
);
|
|
||||||
productName = Burrow;
|
productName = Burrow;
|
||||||
productReference = D05B9F7229E39EEC008CB1F9 /* Burrow.app */;
|
productReference = D05B9F7229E39EEC008CB1F9 /* Burrow.app */;
|
||||||
productType = "com.apple.product-type.application";
|
productType = "com.apple.product-type.application";
|
||||||
};
|
};
|
||||||
D0D4E5302C8D996F007F820A /* Core */ = {
|
|
||||||
isa = PBXNativeTarget;
|
|
||||||
buildConfigurationList = D0D4E53C2C8D996F007F820A /* Build configuration list for PBXNativeTarget "Core" */;
|
|
||||||
buildPhases = (
|
|
||||||
D0D4E52D2C8D996F007F820A /* Sources */,
|
|
||||||
D078F7CF2C8DA213008A8CEC /* Frameworks */,
|
|
||||||
);
|
|
||||||
buildRules = (
|
|
||||||
);
|
|
||||||
dependencies = (
|
|
||||||
D0F7598A2C8DB34200126CF3 /* PBXTargetDependency */,
|
|
||||||
);
|
|
||||||
name = Core;
|
|
||||||
packageProductDependencies = (
|
|
||||||
D078F7E02C8DA375008A8CEC /* GRPC */,
|
|
||||||
D078F7E22C8DA375008A8CEC /* SwiftProtobuf */,
|
|
||||||
D044EE902C8DAB2000778185 /* NIO */,
|
|
||||||
D044EE922C8DAB2000778185 /* NIOConcurrencyHelpers */,
|
|
||||||
D044EE952C8DAB2800778185 /* NIOTransportServices */,
|
|
||||||
D0F7597D2C8DB30500126CF3 /* CGRPCZlib */,
|
|
||||||
);
|
|
||||||
productName = Core;
|
|
||||||
productReference = D0D4E5312C8D996F007F820A /* BurrowCore.framework */;
|
|
||||||
productType = "com.apple.product-type.framework";
|
|
||||||
};
|
|
||||||
D0D4E5502C8D9BF2007F820A /* UI */ = {
|
|
||||||
isa = PBXNativeTarget;
|
|
||||||
buildConfigurationList = D0D4E5552C8D9BF2007F820A /* Build configuration list for PBXNativeTarget "UI" */;
|
|
||||||
buildPhases = (
|
|
||||||
D0D4E5522C8D9BF2007F820A /* Sources */,
|
|
||||||
D0D4E5532C8D9BF2007F820A /* Frameworks */,
|
|
||||||
D0D4E5542C8D9BF2007F820A /* Resources */,
|
|
||||||
);
|
|
||||||
buildRules = (
|
|
||||||
);
|
|
||||||
dependencies = (
|
|
||||||
D0D4E56F2C8D9C5D007F820A /* PBXTargetDependency */,
|
|
||||||
);
|
|
||||||
name = UI;
|
|
||||||
packageProductDependencies = (
|
|
||||||
D0A11C0F2F90000100112233 /* DequeModule */,
|
|
||||||
);
|
|
||||||
productName = Core;
|
|
||||||
productReference = D0D4E5582C8D9BF2007F820A /* BurrowUI.framework */;
|
|
||||||
productType = "com.apple.product-type.framework";
|
|
||||||
};
|
|
||||||
D0D4E55A2C8D9BF4007F820A /* Configuration */ = {
|
|
||||||
isa = PBXNativeTarget;
|
|
||||||
buildConfigurationList = D0D4E55F2C8D9BF4007F820A /* Build configuration list for PBXNativeTarget "Configuration" */;
|
|
||||||
buildPhases = (
|
|
||||||
D0F759912C8DB49E00126CF3 /* Configure Version */,
|
|
||||||
D0D4E55C2C8D9BF4007F820A /* Sources */,
|
|
||||||
);
|
|
||||||
buildRules = (
|
|
||||||
);
|
|
||||||
dependencies = (
|
|
||||||
);
|
|
||||||
name = Configuration;
|
|
||||||
packageProductDependencies = (
|
|
||||||
);
|
|
||||||
productName = Core;
|
|
||||||
productReference = D0D4E5622C8D9BF4007F820A /* BurrowConfiguration.framework */;
|
|
||||||
productType = "com.apple.product-type.framework";
|
|
||||||
};
|
|
||||||
/* End PBXNativeTarget section */
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
/* Begin PBXProject section */
|
/* Begin PBXProject section */
|
||||||
|
|
@ -543,22 +179,15 @@
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
BuildIndependentTargetsInParallel = 1;
|
BuildIndependentTargetsInParallel = 1;
|
||||||
LastSwiftUpdateCheck = 1600;
|
LastSwiftUpdateCheck = 1430;
|
||||||
LastUpgradeCheck = 1520;
|
LastUpgradeCheck = 1430;
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
D11000082F70000100112233 = {
|
|
||||||
CreatedOnToolsVersion = 16.0;
|
|
||||||
TestTargetID = D05B9F7129E39EEC008CB1F9;
|
|
||||||
};
|
|
||||||
D020F65229E4A697002790F6 = {
|
D020F65229E4A697002790F6 = {
|
||||||
CreatedOnToolsVersion = 14.3;
|
CreatedOnToolsVersion = 14.3;
|
||||||
};
|
};
|
||||||
D05B9F7129E39EEC008CB1F9 = {
|
D05B9F7129E39EEC008CB1F9 = {
|
||||||
CreatedOnToolsVersion = 14.3;
|
CreatedOnToolsVersion = 14.3;
|
||||||
};
|
};
|
||||||
D0D4E5302C8D996F007F820A = {
|
|
||||||
CreatedOnToolsVersion = 16.0;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
buildConfigurationList = D05B9F6D29E39EEC008CB1F9 /* Build configuration list for PBXProject "Burrow" */;
|
buildConfigurationList = D05B9F6D29E39EEC008CB1F9 /* Build configuration list for PBXProject "Burrow" */;
|
||||||
|
|
@ -570,31 +199,18 @@
|
||||||
Base,
|
Base,
|
||||||
);
|
);
|
||||||
mainGroup = D05B9F6929E39EEC008CB1F9;
|
mainGroup = D05B9F6929E39EEC008CB1F9;
|
||||||
packageReferences = (
|
|
||||||
D0B1D10E2C436152004B7823 /* XCRemoteSwiftPackageReference "swift-async-algorithms" */,
|
|
||||||
D0D4E4822C8D8EF6007F820A /* XCRemoteSwiftPackageReference "grpc-swift" */,
|
|
||||||
D0D4E4852C8D8F29007F820A /* XCRemoteSwiftPackageReference "swift-protobuf" */,
|
|
||||||
D044EE8F2C8DAB2000778185 /* XCRemoteSwiftPackageReference "swift-nio" */,
|
|
||||||
D044EE942C8DAB2800778185 /* XCRemoteSwiftPackageReference "swift-nio-transport-services" */,
|
|
||||||
D0A11C0D2F90000100112233 /* XCRemoteSwiftPackageReference "swift-collections" */,
|
|
||||||
D0C0DE112FA0000100112233 /* XCRemoteSwiftPackageReference "Sparkle" */,
|
|
||||||
);
|
|
||||||
productRefGroup = D05B9F7329E39EEC008CB1F9 /* Products */;
|
productRefGroup = D05B9F7329E39EEC008CB1F9 /* Products */;
|
||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
projectRoot = "";
|
projectRoot = "";
|
||||||
targets = (
|
targets = (
|
||||||
D05B9F7129E39EEC008CB1F9 /* App */,
|
D05B9F7129E39EEC008CB1F9 /* Burrow */,
|
||||||
D11000082F70000100112233 /* BurrowUITests */,
|
|
||||||
D020F65229E4A697002790F6 /* NetworkExtension */,
|
D020F65229E4A697002790F6 /* NetworkExtension */,
|
||||||
D0D4E5502C8D9BF2007F820A /* UI */,
|
|
||||||
D0D4E5302C8D996F007F820A /* Core */,
|
|
||||||
D0D4E55A2C8D9BF4007F820A /* Configuration */,
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
|
|
||||||
/* Begin PBXResourcesBuildPhase section */
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
D11000092F70000100112233 /* Resources */ = {
|
D020F65129E4A697002790F6 /* Resources */ = {
|
||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
|
@ -605,74 +221,13 @@
|
||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
D09150422B9D2AF700BE3CB0 /* MainMenu.xib in Resources */,
|
D05B9F7A29E39EED008CB1F9 /* Assets.xcassets in Resources */,
|
||||||
D0D4E5812C8D9C94007F820A /* Assets.xcassets in Resources */,
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
D0D4E5542C8D9BF2007F820A /* Resources */ = {
|
|
||||||
isa = PBXResourcesBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
/* End PBXResourcesBuildPhase section */
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXShellScriptBuildPhase section */
|
|
||||||
D0BCC60B2A09A0C100AD070D /* Compile Rust */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
alwaysOutOfDate = 1;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputFileListPaths = (
|
|
||||||
);
|
|
||||||
inputPaths = (
|
|
||||||
);
|
|
||||||
name = "Compile Rust";
|
|
||||||
outputFileListPaths = (
|
|
||||||
);
|
|
||||||
outputPaths = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "\"${PROJECT_DIR}/NetworkExtension/libburrow/build-rust.sh\"\n";
|
|
||||||
showEnvVarsInLog = 0;
|
|
||||||
};
|
|
||||||
D0F759912C8DB49E00126CF3 /* Configure Version */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputFileListPaths = (
|
|
||||||
);
|
|
||||||
inputPaths = (
|
|
||||||
"$(PROJECT_DIR)/../Tools/version.sh",
|
|
||||||
"$(PROJECT_DIR)/../.git",
|
|
||||||
);
|
|
||||||
name = "Configure Version";
|
|
||||||
outputFileListPaths = (
|
|
||||||
);
|
|
||||||
outputPaths = (
|
|
||||||
"$(PROJECT_DIR)/Configuration/Version.xcconfig",
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "\"$PROJECT_DIR/../Tools/version.sh\"\n";
|
|
||||||
showEnvVarsInLog = 0;
|
|
||||||
};
|
|
||||||
/* End PBXShellScriptBuildPhase section */
|
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
D110000A2F70000100112233 /* Sources */ = {
|
|
||||||
isa = PBXSourcesBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
D11000012F70000100112233 /* BurrowUITests.swift in Sources */,
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
D020F64F29E4A697002790F6 /* Sources */ = {
|
D020F64F29E4A697002790F6 /* Sources */ = {
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
|
@ -685,113 +240,22 @@
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
D00AA8972A4669BC005C8102 /* AppDelegate.swift in Sources */,
|
D05B9F7829E39EEC008CB1F9 /* ContentView.swift in Sources */,
|
||||||
D05B9F7629E39EEC008CB1F9 /* BurrowApp.swift in Sources */,
|
D05B9F7629E39EEC008CB1F9 /* BurrowApp.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
D0D4E52D2C8D996F007F820A /* Sources */ = {
|
|
||||||
isa = PBXSourcesBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
D0FA10012D10200100112233 /* burrow.pb.swift in Sources */,
|
|
||||||
D0FA10022D10200100112233 /* burrow.grpc.swift in Sources */,
|
|
||||||
D0F7598D2C8DB3DA00126CF3 /* Client.swift in Sources */,
|
|
||||||
D0D4E56B2C8D9C2F007F820A /* Logging.swift in Sources */,
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
D0D4E5522C8D9BF2007F820A /* Sources */ = {
|
|
||||||
isa = PBXSourcesBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
D0D4E5722C8D9C6F007F820A /* Network.swift in Sources */,
|
|
||||||
D0D4E5732C8D9C6F007F820A /* WireGuard.swift in Sources */,
|
|
||||||
D0D4E5742C8D9C6F007F820A /* BurrowView.swift in Sources */,
|
|
||||||
D0D4E5752C8D9C6F007F820A /* FloatingButtonStyle.swift in Sources */,
|
|
||||||
D0D4E5762C8D9C6F007F820A /* MenuItemToggleView.swift in Sources */,
|
|
||||||
D0D4E5772C8D9C6F007F820A /* NetworkCarouselView.swift in Sources */,
|
|
||||||
D0D4E5782C8D9C6F007F820A /* NetworkExtension+Async.swift in Sources */,
|
|
||||||
D0D4E5792C8D9C6F007F820A /* NetworkExtensionTunnel.swift in Sources */,
|
|
||||||
D0D4E57A2C8D9C6F007F820A /* NetworkView.swift in Sources */,
|
|
||||||
D0D4E57C2C8D9C6F007F820A /* Tunnel.swift in Sources */,
|
|
||||||
D0D4E57D2C8D9C6F007F820A /* TunnelButton.swift in Sources */,
|
|
||||||
D0D4E57E2C8D9C6F007F820A /* TunnelStatusView.swift in Sources */,
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
D0D4E55C2C8D9BF4007F820A /* Sources */ = {
|
|
||||||
isa = PBXSourcesBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
D0D4E5922C8D9D15007F820A /* Constants.swift in Sources */,
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
/* End PBXSourcesBuildPhase section */
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXTargetDependency section */
|
/* Begin PBXTargetDependency section */
|
||||||
D110000B2F70000100112233 /* PBXTargetDependency */ = {
|
|
||||||
isa = PBXTargetDependency;
|
|
||||||
target = D05B9F7129E39EEC008CB1F9 /* App */;
|
|
||||||
targetProxy = D11000022F70000100112233 /* PBXContainerItemProxy */;
|
|
||||||
};
|
|
||||||
D020F65C29E4A697002790F6 /* PBXTargetDependency */ = {
|
D020F65C29E4A697002790F6 /* PBXTargetDependency */ = {
|
||||||
isa = PBXTargetDependency;
|
isa = PBXTargetDependency;
|
||||||
target = D020F65229E4A697002790F6 /* NetworkExtension */;
|
target = D020F65229E4A697002790F6 /* NetworkExtension */;
|
||||||
targetProxy = D020F65B29E4A697002790F6 /* PBXContainerItemProxy */;
|
targetProxy = D020F65B29E4A697002790F6 /* PBXContainerItemProxy */;
|
||||||
};
|
};
|
||||||
D0BF09512C8E66F1000D8DEC /* PBXTargetDependency */ = {
|
|
||||||
isa = PBXTargetDependency;
|
|
||||||
target = D0D4E55A2C8D9BF4007F820A /* Configuration */;
|
|
||||||
targetProxy = D0BF09502C8E66F1000D8DEC /* PBXContainerItemProxy */;
|
|
||||||
};
|
|
||||||
D0BF09542C8E66FA000D8DEC /* PBXTargetDependency */ = {
|
|
||||||
isa = PBXTargetDependency;
|
|
||||||
target = D0D4E55A2C8D9BF4007F820A /* Configuration */;
|
|
||||||
targetProxy = D0BF09532C8E66FA000D8DEC /* PBXContainerItemProxy */;
|
|
||||||
};
|
|
||||||
D0D4E56F2C8D9C5D007F820A /* PBXTargetDependency */ = {
|
|
||||||
isa = PBXTargetDependency;
|
|
||||||
target = D0D4E5302C8D996F007F820A /* Core */;
|
|
||||||
targetProxy = D0D4E56E2C8D9C5D007F820A /* PBXContainerItemProxy */;
|
|
||||||
};
|
|
||||||
D0D4E5802C8D9C78007F820A /* PBXTargetDependency */ = {
|
|
||||||
isa = PBXTargetDependency;
|
|
||||||
target = D0D4E5302C8D996F007F820A /* Core */;
|
|
||||||
targetProxy = D0D4E57F2C8D9C78007F820A /* PBXContainerItemProxy */;
|
|
||||||
};
|
|
||||||
D0D4E5882C8D9C88007F820A /* PBXTargetDependency */ = {
|
|
||||||
isa = PBXTargetDependency;
|
|
||||||
target = D0D4E5502C8D9BF2007F820A /* UI */;
|
|
||||||
targetProxy = D0D4E5872C8D9C88007F820A /* PBXContainerItemProxy */;
|
|
||||||
};
|
|
||||||
D0F4FAD22C8DC7960068730A /* PBXTargetDependency */ = {
|
|
||||||
isa = PBXTargetDependency;
|
|
||||||
target = D0D4E5302C8D996F007F820A /* Core */;
|
|
||||||
targetProxy = D0F4FAD12C8DC7960068730A /* PBXContainerItemProxy */;
|
|
||||||
};
|
|
||||||
D0F7598A2C8DB34200126CF3 /* PBXTargetDependency */ = {
|
|
||||||
isa = PBXTargetDependency;
|
|
||||||
productRef = D0F759892C8DB34200126CF3 /* GRPC */;
|
|
||||||
};
|
|
||||||
/* End PBXTargetDependency section */
|
/* End PBXTargetDependency section */
|
||||||
|
|
||||||
/* Begin XCBuildConfiguration section */
|
/* Begin XCBuildConfiguration section */
|
||||||
D110000C2F70000100112233 /* Debug */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
baseConfigurationReference = D11000052F70000100112233 /* UITests.xcconfig */;
|
|
||||||
buildSettings = {
|
|
||||||
};
|
|
||||||
name = Debug;
|
|
||||||
};
|
|
||||||
D110000D2F70000100112233 /* Release */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
baseConfigurationReference = D11000052F70000100112233 /* UITests.xcconfig */;
|
|
||||||
buildSettings = {
|
|
||||||
};
|
|
||||||
name = Release;
|
|
||||||
};
|
|
||||||
D020F65F29E4A697002790F6 /* Debug */ = {
|
D020F65F29E4A697002790F6 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = D020F66229E4A6E5002790F6 /* NetworkExtension.xcconfig */;
|
baseConfigurationReference = D020F66229E4A6E5002790F6 /* NetworkExtension.xcconfig */;
|
||||||
|
|
@ -822,56 +286,14 @@
|
||||||
};
|
};
|
||||||
D05B9F8229E39EED008CB1F9 /* Debug */ = {
|
D05B9F8229E39EED008CB1F9 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = D020F64929E4A34B002790F6 /* App.xcconfig */;
|
baseConfigurationReference = D020F64929E4A34B002790F6 /* Burrow.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
};
|
};
|
||||||
D05B9F8329E39EED008CB1F9 /* Release */ = {
|
D05B9F8329E39EED008CB1F9 /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = D020F64929E4A34B002790F6 /* App.xcconfig */;
|
baseConfigurationReference = D020F64929E4A34B002790F6 /* Burrow.xcconfig */;
|
||||||
buildSettings = {
|
|
||||||
};
|
|
||||||
name = Release;
|
|
||||||
};
|
|
||||||
D0D4E53D2C8D996F007F820A /* Debug */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
baseConfigurationReference = D0D4E4F72C8D941D007F820A /* Framework.xcconfig */;
|
|
||||||
buildSettings = {
|
|
||||||
};
|
|
||||||
name = Debug;
|
|
||||||
};
|
|
||||||
D0D4E53E2C8D996F007F820A /* Release */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
baseConfigurationReference = D0D4E4F72C8D941D007F820A /* Framework.xcconfig */;
|
|
||||||
buildSettings = {
|
|
||||||
};
|
|
||||||
name = Release;
|
|
||||||
};
|
|
||||||
D0D4E5562C8D9BF2007F820A /* Debug */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
baseConfigurationReference = D0BF09582C8E6789000D8DEC /* UI.xcconfig */;
|
|
||||||
buildSettings = {
|
|
||||||
};
|
|
||||||
name = Debug;
|
|
||||||
};
|
|
||||||
D0D4E5572C8D9BF2007F820A /* Release */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
baseConfigurationReference = D0BF09582C8E6789000D8DEC /* UI.xcconfig */;
|
|
||||||
buildSettings = {
|
|
||||||
};
|
|
||||||
name = Release;
|
|
||||||
};
|
|
||||||
D0D4E5602C8D9BF4007F820A /* Debug */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
baseConfigurationReference = D00117422B30348D00D87C25 /* Configuration.xcconfig */;
|
|
||||||
buildSettings = {
|
|
||||||
};
|
|
||||||
name = Debug;
|
|
||||||
};
|
|
||||||
D0D4E5612C8D9BF4007F820A /* Release */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
baseConfigurationReference = D00117422B30348D00D87C25 /* Configuration.xcconfig */;
|
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
|
|
@ -879,15 +301,6 @@
|
||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
/* Begin XCConfigurationList section */
|
||||||
D110000E2F70000100112233 /* Build configuration list for PBXNativeTarget "BurrowUITests" */ = {
|
|
||||||
isa = XCConfigurationList;
|
|
||||||
buildConfigurations = (
|
|
||||||
D110000C2F70000100112233 /* Debug */,
|
|
||||||
D110000D2F70000100112233 /* Release */,
|
|
||||||
);
|
|
||||||
defaultConfigurationIsVisible = 0;
|
|
||||||
defaultConfigurationName = Release;
|
|
||||||
};
|
|
||||||
D020F65E29E4A697002790F6 /* Build configuration list for PBXNativeTarget "NetworkExtension" */ = {
|
D020F65E29E4A697002790F6 /* Build configuration list for PBXNativeTarget "NetworkExtension" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
|
|
@ -906,7 +319,7 @@
|
||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
D05B9F8129E39EED008CB1F9 /* Build configuration list for PBXNativeTarget "App" */ = {
|
D05B9F8129E39EED008CB1F9 /* Build configuration list for PBXNativeTarget "Burrow" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
D05B9F8229E39EED008CB1F9 /* Debug */,
|
D05B9F8229E39EED008CB1F9 /* Debug */,
|
||||||
|
|
@ -915,146 +328,7 @@
|
||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
D0D4E53C2C8D996F007F820A /* Build configuration list for PBXNativeTarget "Core" */ = {
|
|
||||||
isa = XCConfigurationList;
|
|
||||||
buildConfigurations = (
|
|
||||||
D0D4E53D2C8D996F007F820A /* Debug */,
|
|
||||||
D0D4E53E2C8D996F007F820A /* Release */,
|
|
||||||
);
|
|
||||||
defaultConfigurationIsVisible = 0;
|
|
||||||
defaultConfigurationName = Release;
|
|
||||||
};
|
|
||||||
D0D4E5552C8D9BF2007F820A /* Build configuration list for PBXNativeTarget "UI" */ = {
|
|
||||||
isa = XCConfigurationList;
|
|
||||||
buildConfigurations = (
|
|
||||||
D0D4E5562C8D9BF2007F820A /* Debug */,
|
|
||||||
D0D4E5572C8D9BF2007F820A /* Release */,
|
|
||||||
);
|
|
||||||
defaultConfigurationIsVisible = 0;
|
|
||||||
defaultConfigurationName = Release;
|
|
||||||
};
|
|
||||||
D0D4E55F2C8D9BF4007F820A /* Build configuration list for PBXNativeTarget "Configuration" */ = {
|
|
||||||
isa = XCConfigurationList;
|
|
||||||
buildConfigurations = (
|
|
||||||
D0D4E5602C8D9BF4007F820A /* Debug */,
|
|
||||||
D0D4E5612C8D9BF4007F820A /* Release */,
|
|
||||||
);
|
|
||||||
defaultConfigurationIsVisible = 0;
|
|
||||||
defaultConfigurationName = Release;
|
|
||||||
};
|
|
||||||
/* End XCConfigurationList section */
|
/* End XCConfigurationList section */
|
||||||
|
|
||||||
/* Begin XCRemoteSwiftPackageReference section */
|
|
||||||
D044EE8F2C8DAB2000778185 /* XCRemoteSwiftPackageReference "swift-nio" */ = {
|
|
||||||
isa = XCRemoteSwiftPackageReference;
|
|
||||||
repositoryURL = "https://github.com/apple/swift-nio.git";
|
|
||||||
requirement = {
|
|
||||||
kind = upToNextMajorVersion;
|
|
||||||
minimumVersion = 2.72.0;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
D044EE942C8DAB2800778185 /* XCRemoteSwiftPackageReference "swift-nio-transport-services" */ = {
|
|
||||||
isa = XCRemoteSwiftPackageReference;
|
|
||||||
repositoryURL = "https://github.com/apple/swift-nio-transport-services.git";
|
|
||||||
requirement = {
|
|
||||||
kind = upToNextMajorVersion;
|
|
||||||
minimumVersion = 1.21.0;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
D0A11C0D2F90000100112233 /* XCRemoteSwiftPackageReference "swift-collections" */ = {
|
|
||||||
isa = XCRemoteSwiftPackageReference;
|
|
||||||
repositoryURL = "https://github.com/apple/swift-collections.git";
|
|
||||||
requirement = {
|
|
||||||
kind = upToNextMajorVersion;
|
|
||||||
minimumVersion = 1.1.3;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
D0B1D10E2C436152004B7823 /* XCRemoteSwiftPackageReference "swift-async-algorithms" */ = {
|
|
||||||
isa = XCRemoteSwiftPackageReference;
|
|
||||||
repositoryURL = "https://github.com/apple/swift-async-algorithms.git";
|
|
||||||
requirement = {
|
|
||||||
kind = upToNextMajorVersion;
|
|
||||||
minimumVersion = 1.0.1;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
D0C0DE112FA0000100112233 /* XCRemoteSwiftPackageReference "Sparkle" */ = {
|
|
||||||
isa = XCRemoteSwiftPackageReference;
|
|
||||||
repositoryURL = "https://github.com/sparkle-project/Sparkle.git";
|
|
||||||
requirement = {
|
|
||||||
kind = upToNextMajorVersion;
|
|
||||||
minimumVersion = 2.9.2;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
D0D4E4822C8D8EF6007F820A /* XCRemoteSwiftPackageReference "grpc-swift" */ = {
|
|
||||||
isa = XCRemoteSwiftPackageReference;
|
|
||||||
repositoryURL = "https://github.com/grpc/grpc-swift.git";
|
|
||||||
requirement = {
|
|
||||||
kind = upToNextMajorVersion;
|
|
||||||
minimumVersion = 1.23.0;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
D0D4E4852C8D8F29007F820A /* XCRemoteSwiftPackageReference "swift-protobuf" */ = {
|
|
||||||
isa = XCRemoteSwiftPackageReference;
|
|
||||||
repositoryURL = "https://github.com/apple/swift-protobuf.git";
|
|
||||||
requirement = {
|
|
||||||
kind = upToNextMajorVersion;
|
|
||||||
minimumVersion = 1.28.1;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
/* End XCRemoteSwiftPackageReference section */
|
|
||||||
|
|
||||||
/* Begin XCSwiftPackageProductDependency section */
|
|
||||||
D044EE902C8DAB2000778185 /* NIO */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
package = D044EE8F2C8DAB2000778185 /* XCRemoteSwiftPackageReference "swift-nio" */;
|
|
||||||
productName = NIO;
|
|
||||||
};
|
|
||||||
D044EE922C8DAB2000778185 /* NIOConcurrencyHelpers */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
package = D044EE8F2C8DAB2000778185 /* XCRemoteSwiftPackageReference "swift-nio" */;
|
|
||||||
productName = NIOConcurrencyHelpers;
|
|
||||||
};
|
|
||||||
D044EE952C8DAB2800778185 /* NIOTransportServices */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
package = D044EE942C8DAB2800778185 /* XCRemoteSwiftPackageReference "swift-nio-transport-services" */;
|
|
||||||
productName = NIOTransportServices;
|
|
||||||
};
|
|
||||||
D078F7E02C8DA375008A8CEC /* GRPC */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
package = D0D4E4822C8D8EF6007F820A /* XCRemoteSwiftPackageReference "grpc-swift" */;
|
|
||||||
productName = GRPC;
|
|
||||||
};
|
|
||||||
D078F7E22C8DA375008A8CEC /* SwiftProtobuf */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
package = D0D4E4852C8D8F29007F820A /* XCRemoteSwiftPackageReference "swift-protobuf" */;
|
|
||||||
productName = SwiftProtobuf;
|
|
||||||
};
|
|
||||||
D0A11C0F2F90000100112233 /* DequeModule */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
package = D0A11C0D2F90000100112233 /* XCRemoteSwiftPackageReference "swift-collections" */;
|
|
||||||
productName = DequeModule;
|
|
||||||
};
|
|
||||||
D0B1D10F2C436152004B7823 /* AsyncAlgorithms */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
package = D0B1D10E2C436152004B7823 /* XCRemoteSwiftPackageReference "swift-async-algorithms" */;
|
|
||||||
productName = AsyncAlgorithms;
|
|
||||||
};
|
|
||||||
D0C0DE122FA0000100112233 /* Sparkle */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
package = D0C0DE112FA0000100112233 /* XCRemoteSwiftPackageReference "Sparkle" */;
|
|
||||||
productName = Sparkle;
|
|
||||||
};
|
|
||||||
D0F7597D2C8DB30500126CF3 /* CGRPCZlib */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
package = D0D4E4822C8D8EF6007F820A /* XCRemoteSwiftPackageReference "grpc-swift" */;
|
|
||||||
productName = CGRPCZlib;
|
|
||||||
};
|
|
||||||
D0F759892C8DB34200126CF3 /* GRPC */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
package = D0D4E4822C8D8EF6007F820A /* XCRemoteSwiftPackageReference "grpc-swift" */;
|
|
||||||
productName = GRPC;
|
|
||||||
};
|
|
||||||
/* End XCSwiftPackageProductDependency section */
|
|
||||||
};
|
};
|
||||||
rootObject = D05B9F6A29E39EEC008CB1F9 /* Project object */;
|
rootObject = D05B9F6A29E39EEC008CB1F9 /* Project object */;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded</key>
|
|
||||||
<false/>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
||||||
|
|
@ -1,132 +0,0 @@
|
||||||
{
|
|
||||||
"originHash" : "5d81b59cbecacd7aae6aa598b32e3513c636250dadab9280a55b905bb0e0ee60",
|
|
||||||
"pins" : [
|
|
||||||
{
|
|
||||||
"identity" : "grpc-swift",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/grpc/grpc-swift.git",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "6a90b7e77e29f9bda6c2b3a4165a40d6c02cfda1",
|
|
||||||
"version" : "1.23.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"identity" : "sparkle",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/sparkle-project/Sparkle.git",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "6276ba2b404829d139c45ff98427cf90e2efc59b",
|
|
||||||
"version" : "2.9.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"identity" : "swift-async-algorithms",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/apple/swift-async-algorithms.git",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "6ae9a051f76b81cc668305ceed5b0e0a7fd93d20",
|
|
||||||
"version" : "1.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"identity" : "swift-atomics",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/apple/swift-atomics.git",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "cd142fd2f64be2100422d658e7411e39489da985",
|
|
||||||
"version" : "1.2.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"identity" : "swift-collections",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/apple/swift-collections.git",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "9bf03ff58ce34478e66aaee630e491823326fd06",
|
|
||||||
"version" : "1.1.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"identity" : "swift-http-types",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/apple/swift-http-types",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "ae67c8178eb46944fd85e4dc6dd970e1f3ed6ccd",
|
|
||||||
"version" : "1.3.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"identity" : "swift-log",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/apple/swift-log.git",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "9cb486020ebf03bfa5b5df985387a14a98744537",
|
|
||||||
"version" : "1.6.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"identity" : "swift-nio",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/apple/swift-nio.git",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "9746cf80e29edfef2a39924a66731249223f42a3",
|
|
||||||
"version" : "2.72.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"identity" : "swift-nio-extras",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/apple/swift-nio-extras.git",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "d1ead62745cc3269e482f1c51f27608057174379",
|
|
||||||
"version" : "1.24.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"identity" : "swift-nio-http2",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/apple/swift-nio-http2.git",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "b5f7062b60e4add1e8c343ba4eb8da2e324b3a94",
|
|
||||||
"version" : "1.34.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"identity" : "swift-nio-ssl",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/apple/swift-nio-ssl.git",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "7b84abbdcef69cc3be6573ac12440220789dcd69",
|
|
||||||
"version" : "2.27.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"identity" : "swift-nio-transport-services",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/apple/swift-nio-transport-services.git",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "38ac8221dd20674682148d6451367f89c2652980",
|
|
||||||
"version" : "1.21.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"identity" : "swift-protobuf",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/apple/swift-protobuf.git",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "edb6ed4919f7756157fe02f2552b7e3850a538e5",
|
|
||||||
"version" : "1.28.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"identity" : "swift-system",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/apple/swift-system.git",
|
|
||||||
"state" : {
|
|
||||||
"revision" : "d2ba781702a1d8285419c15ee62fd734a9437ff5",
|
|
||||||
"version" : "1.3.2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"version" : 3
|
|
||||||
}
|
|
||||||
|
|
@ -1,91 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<Scheme
|
|
||||||
LastUpgradeVersion = "1600"
|
|
||||||
version = "1.7">
|
|
||||||
<BuildAction
|
|
||||||
parallelizeBuildables = "YES"
|
|
||||||
buildImplicitDependencies = "YES"
|
|
||||||
buildArchitectures = "Automatic">
|
|
||||||
<BuildActionEntries>
|
|
||||||
<BuildActionEntry
|
|
||||||
buildForTesting = "YES"
|
|
||||||
buildForRunning = "YES"
|
|
||||||
buildForProfiling = "YES"
|
|
||||||
buildForArchiving = "YES"
|
|
||||||
buildForAnalyzing = "YES">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "D05B9F7129E39EEC008CB1F9"
|
|
||||||
BuildableName = "Burrow.app"
|
|
||||||
BlueprintName = "App"
|
|
||||||
ReferencedContainer = "container:Burrow.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildActionEntry>
|
|
||||||
</BuildActionEntries>
|
|
||||||
</BuildAction>
|
|
||||||
<TestAction
|
|
||||||
buildConfiguration = "Debug"
|
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
|
||||||
shouldAutocreateTestPlan = "NO">
|
|
||||||
<Testables>
|
|
||||||
<TestableReference
|
|
||||||
skipped = "NO"
|
|
||||||
parallelizable = "YES">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "D11000082F70000100112233"
|
|
||||||
BuildableName = "BurrowUITests.xctest"
|
|
||||||
BlueprintName = "BurrowUITests"
|
|
||||||
ReferencedContainer = "container:Burrow.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</TestableReference>
|
|
||||||
</Testables>
|
|
||||||
</TestAction>
|
|
||||||
<LaunchAction
|
|
||||||
buildConfiguration = "Debug"
|
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
|
||||||
launchStyle = "0"
|
|
||||||
useCustomWorkingDirectory = "NO"
|
|
||||||
ignoresPersistentStateOnLaunch = "NO"
|
|
||||||
debugDocumentVersioning = "YES"
|
|
||||||
debugServiceExtension = "internal"
|
|
||||||
allowLocationSimulation = "YES">
|
|
||||||
<BuildableProductRunnable
|
|
||||||
runnableDebuggingMode = "0">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "D05B9F7129E39EEC008CB1F9"
|
|
||||||
BuildableName = "Burrow.app"
|
|
||||||
BlueprintName = "App"
|
|
||||||
ReferencedContainer = "container:Burrow.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildableProductRunnable>
|
|
||||||
</LaunchAction>
|
|
||||||
<ProfileAction
|
|
||||||
buildConfiguration = "Release"
|
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
|
||||||
savedToolIdentifier = ""
|
|
||||||
useCustomWorkingDirectory = "NO"
|
|
||||||
debugDocumentVersioning = "YES">
|
|
||||||
<BuildableProductRunnable
|
|
||||||
runnableDebuggingMode = "0">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "D05B9F7129E39EEC008CB1F9"
|
|
||||||
BuildableName = "Burrow.app"
|
|
||||||
BlueprintName = "App"
|
|
||||||
ReferencedContainer = "container:Burrow.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildableProductRunnable>
|
|
||||||
</ProfileAction>
|
|
||||||
<AnalyzeAction
|
|
||||||
buildConfiguration = "Debug">
|
|
||||||
</AnalyzeAction>
|
|
||||||
<ArchiveAction
|
|
||||||
buildConfiguration = "Release"
|
|
||||||
revealArchiveInOrganizer = "YES">
|
|
||||||
</ArchiveAction>
|
|
||||||
</Scheme>
|
|
||||||
|
|
@ -1,97 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<Scheme
|
|
||||||
LastUpgradeVersion = "1600"
|
|
||||||
wasCreatedForAppExtension = "YES"
|
|
||||||
version = "2.0">
|
|
||||||
<BuildAction
|
|
||||||
parallelizeBuildables = "YES"
|
|
||||||
buildImplicitDependencies = "YES"
|
|
||||||
buildArchitectures = "Automatic">
|
|
||||||
<BuildActionEntries>
|
|
||||||
<BuildActionEntry
|
|
||||||
buildForTesting = "YES"
|
|
||||||
buildForRunning = "YES"
|
|
||||||
buildForProfiling = "YES"
|
|
||||||
buildForArchiving = "YES"
|
|
||||||
buildForAnalyzing = "YES">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "D020F65229E4A697002790F6"
|
|
||||||
BuildableName = "BurrowNetworkExtension.appex"
|
|
||||||
BlueprintName = "NetworkExtension"
|
|
||||||
ReferencedContainer = "container:Burrow.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildActionEntry>
|
|
||||||
<BuildActionEntry
|
|
||||||
buildForTesting = "YES"
|
|
||||||
buildForRunning = "YES"
|
|
||||||
buildForProfiling = "YES"
|
|
||||||
buildForArchiving = "YES"
|
|
||||||
buildForAnalyzing = "YES">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "D05B9F7129E39EEC008CB1F9"
|
|
||||||
BuildableName = "Burrow.app"
|
|
||||||
BlueprintName = "App"
|
|
||||||
ReferencedContainer = "container:Burrow.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildActionEntry>
|
|
||||||
</BuildActionEntries>
|
|
||||||
</BuildAction>
|
|
||||||
<TestAction
|
|
||||||
buildConfiguration = "Debug"
|
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
|
||||||
shouldAutocreateTestPlan = "YES">
|
|
||||||
</TestAction>
|
|
||||||
<LaunchAction
|
|
||||||
buildConfiguration = "Debug"
|
|
||||||
selectedDebuggerIdentifier = ""
|
|
||||||
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
|
|
||||||
launchStyle = "0"
|
|
||||||
askForAppToLaunch = "Yes"
|
|
||||||
useCustomWorkingDirectory = "NO"
|
|
||||||
ignoresPersistentStateOnLaunch = "NO"
|
|
||||||
debugDocumentVersioning = "YES"
|
|
||||||
debugServiceExtension = "internal"
|
|
||||||
allowLocationSimulation = "YES"
|
|
||||||
launchAutomaticallySubstyle = "2">
|
|
||||||
<BuildableProductRunnable
|
|
||||||
runnableDebuggingMode = "0">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "D05B9F7129E39EEC008CB1F9"
|
|
||||||
BuildableName = "Burrow.app"
|
|
||||||
BlueprintName = "App"
|
|
||||||
ReferencedContainer = "container:Burrow.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildableProductRunnable>
|
|
||||||
</LaunchAction>
|
|
||||||
<ProfileAction
|
|
||||||
buildConfiguration = "Release"
|
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
|
||||||
savedToolIdentifier = ""
|
|
||||||
useCustomWorkingDirectory = "NO"
|
|
||||||
debugDocumentVersioning = "YES"
|
|
||||||
askForAppToLaunch = "Yes"
|
|
||||||
launchAutomaticallySubstyle = "2">
|
|
||||||
<BuildableProductRunnable
|
|
||||||
runnableDebuggingMode = "0">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "D05B9F7129E39EEC008CB1F9"
|
|
||||||
BuildableName = "Burrow.app"
|
|
||||||
BlueprintName = "App"
|
|
||||||
ReferencedContainer = "container:Burrow.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildableProductRunnable>
|
|
||||||
</ProfileAction>
|
|
||||||
<AnalyzeAction
|
|
||||||
buildConfiguration = "Debug">
|
|
||||||
</AnalyzeAction>
|
|
||||||
<ArchiveAction
|
|
||||||
buildConfiguration = "Release"
|
|
||||||
revealArchiveInOrganizer = "YES">
|
|
||||||
</ArchiveAction>
|
|
||||||
</Scheme>
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
# Apple Certificates
|
|
||||||
|
|
||||||
Public Apple certificate material that can be inspected by release tooling lives
|
|
||||||
here. Private keys do not belong in this directory.
|
|
||||||
|
|
||||||
## Developer ID Application
|
|
||||||
|
|
||||||
- Apple certificate id: `9JKN6HXBHC`
|
|
||||||
- Certificate file: `Apple/Certificates/developer-id-application-9JKN6HXBHC.cer`
|
|
||||||
- Subject: `Developer ID Application: Conrad Kramer (87PW93R2ZR)`
|
|
||||||
- Issuer: `Developer ID Certification Authority`, `G2`
|
|
||||||
- Team id: `87PW93R2ZR`
|
|
||||||
- Validity: `2026-06-07T12:13:47Z` through `2031-06-08T12:13:46Z`
|
|
||||||
- SHA-256 fingerprint: `7B:2D:58:A5:BB:1E:34:5E:FB:FF:7F:E0:A1:CA:4F:B1:5B:6E:08:AF:CE:FD:BE:D0:2B:0A:E9:9C:82:E3:4F:74`
|
|
||||||
- Google KMS key:
|
|
||||||
`projects/project-88c23ce9-918a-470a-b33/locations/global/keyRings/burrow-identity/cryptoKeys/apple-developer-id-application/cryptoKeyVersions/1`
|
|
||||||
- KMS public-key SHA-256:
|
|
||||||
`9cfaf4755158f445f20a215ef52e7a7ba00da1a310e2e934ba7db5dbb29d2869`
|
|
||||||
|
|
||||||
The certificate was created from a CSR signed by the non-exportable Google KMS
|
|
||||||
key above. There is no `.p12` for this identity. Release signing must use a
|
|
||||||
signer that delegates the relevant Apple code-signing operations to Google KMS.
|
|
||||||
|
|
||||||
## iOS Distribution
|
|
||||||
|
|
||||||
- Apple certificate id: `3G42677598`
|
|
||||||
- Certificate file: `Apple/Certificates/ios-distribution-3G42677598.cer`
|
|
||||||
- Subject: `iPhone Distribution: Conrad Kramer (87PW93R2ZR)`
|
|
||||||
- Issuer: `Apple Worldwide Developer Relations Certification Authority`, `G3`
|
|
||||||
- Team id: `87PW93R2ZR`
|
|
||||||
- Validity: `2026-06-07T12:21:32Z` through `2027-06-07T12:21:31Z`
|
|
||||||
- SHA-256 fingerprint: `5A:2F:BA:6E:FB:CA:2D:58:01:1F:A0:C8:0F:CF:6B:58:BE:AA:73:7F:4E:F8:06:1C:8A:14:1B:22:8A:2A:29:2B`
|
|
||||||
- Google KMS key:
|
|
||||||
`projects/project-88c23ce9-918a-470a-b33/locations/global/keyRings/burrow-identity/cryptoKeys/apple-ios-distribution/cryptoKeyVersions/1`
|
|
||||||
- KMS public-key SHA-256:
|
|
||||||
`f8613ce059de90b29acf01cbd4a7deb37567653bd154bdf6c447098b5c4fae91`
|
|
||||||
|
|
||||||
The certificate was created from a CSR signed by the non-exportable Google KMS
|
|
||||||
key above through App Store Connect certificate creation. There is no `.p12`
|
|
||||||
for this identity. iOS signing requires a signing path that can delegate Apple
|
|
||||||
code-signing operations to Google KMS.
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
LD_EXPORT_SYMBOLS = NO
|
|
||||||
SKIP_INSTALL = NO
|
SKIP_INSTALL = NO
|
||||||
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks
|
LD_RUNPATH_SEARCH_PATHS[sdk=iphone*] = $(inherited) @executable_path/Frameworks
|
||||||
LD_RUNPATH_SEARCH_PATHS[sdk=macosx*] = $(inherited) @executable_path/../Frameworks
|
LD_RUNPATH_SEARCH_PATHS[sdk=macosx*] = $(inherited) @executable_path/../Frameworks
|
||||||
|
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor
|
||||||
|
|
||||||
|
ENABLE_PREVIEWS = YES
|
||||||
|
|
|
||||||
|
|
@ -1,43 +1,61 @@
|
||||||
#include "Identity.xcconfig"
|
#include "Identity.xcconfig"
|
||||||
#include "Debug.xcconfig"
|
|
||||||
#include "Version.xcconfig"
|
|
||||||
|
|
||||||
SDKROOT = auto
|
SDKROOT = auto
|
||||||
ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES
|
ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES
|
||||||
|
|
||||||
SUPPORTED_PLATFORMS = iphoneos iphonesimulator macosx
|
SUPPORTED_PLATFORMS = iphoneos iphonesimulator macosx
|
||||||
SWIFT_VERSION = 6.0
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 17.0
|
MACOSX_DEPLOYMENT_TARGET = 12.0
|
||||||
MACOSX_DEPLOYMENT_TARGET = 14.0
|
|
||||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO
|
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO
|
||||||
SUPPORTS_MACCATALYST = NO
|
SUPPORTS_MACCATALYST = NO
|
||||||
|
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO
|
||||||
PRODUCT_NAME = $(TARGET_NAME:c99extidentifier)
|
PRODUCT_NAME = $(TARGET_NAME:c99extidentifier)
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = $(APP_BUNDLE_IDENTIFIER).$(PRODUCT_NAME)
|
PRODUCT_BUNDLE_IDENTIFIER = $(APP_BUNDLE_IDENTIFIER).$(PRODUCT_NAME)
|
||||||
|
CURRENT_PROJECT_VERSION = 1
|
||||||
MARKETING_VERSION = 0.1
|
MARKETING_VERSION = 0.1
|
||||||
|
|
||||||
SKIP_INSTALL = YES
|
SKIP_INSTALL = YES
|
||||||
|
|
||||||
CODE_SIGN_IDENTITY = Apple Development
|
CODE_SIGN_IDENTITY = Apple Development
|
||||||
|
|
||||||
GENERATE_INFOPLIST_FILE = YES
|
|
||||||
INFOPLIST_FILE = Configuration/Info.plist
|
INFOPLIST_FILE = Configuration/Info.plist
|
||||||
INFOPLIST_KEY_NSHumanReadableCopyright = Copyright © 2023-2024 Hack Club
|
GENERATE_INFOPLIST_FILE = YES
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = Copyright © 2023 Hack Club
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = Burrow
|
INFOPLIST_KEY_CFBundleDisplayName = Burrow
|
||||||
|
|
||||||
ENABLE_APP_SANDBOX[sdk=macosx*] = YES
|
|
||||||
|
|
||||||
ENABLE_BITCODE = NO
|
ENABLE_BITCODE = NO
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO
|
|
||||||
|
ENABLE_APP_SANDBOX[sdk=macosx*] = YES
|
||||||
|
ENABLE_HARDENED_RUNTIME[sdk=macosx*] = YES
|
||||||
COMBINE_HIDPI_IMAGES = YES
|
COMBINE_HIDPI_IMAGES = YES
|
||||||
EAGER_LINKING = YES
|
COPY_PHASE_STRIP = NO
|
||||||
|
|
||||||
FUSE_BUILD_SCRIPT_PHASES = YES
|
FUSE_BUILD_SCRIPT_PHASES = YES
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES
|
|
||||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES
|
|
||||||
ENABLE_DEBUG_DYLIB = NO
|
|
||||||
|
|
||||||
APP_GROUP_IDENTIFIER = group.$(APP_BUNDLE_IDENTIFIER)
|
APP_GROUP_IDENTIFIER = group.$(APP_BUNDLE_IDENTIFIER)
|
||||||
APP_GROUP_IDENTIFIER[sdk=macosx*] = $(DEVELOPMENT_TEAM).$(APP_BUNDLE_IDENTIFIER)
|
APP_GROUP_IDENTIFIER[sdk=macosx*] = $(DEVELOPMENT_TEAM).$(APP_BUNDLE_IDENTIFIER)
|
||||||
NETWORK_EXTENSION_BUNDLE_IDENTIFIER = $(APP_BUNDLE_IDENTIFIER).network
|
|
||||||
|
|
||||||
OTHER_SWIFT_FLAGS = $(inherited)
|
// Swift
|
||||||
|
SWIFT_VERSION = 5.0
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES
|
||||||
|
|
||||||
|
// Release
|
||||||
|
DEBUG_INFORMATION_FORMAT = dwarf-with-dsym
|
||||||
|
SWIFT_REFLECTION_METADATA_LEVEL = none
|
||||||
|
SWIFT_COMPILATION_MODE = wholemodule
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = -Osize
|
||||||
|
LLVM_LTO = YES
|
||||||
|
DEAD_CODE_STRIPPING = YES
|
||||||
|
VALIDATE_PRODUCT = YES
|
||||||
|
|
||||||
|
// Debug
|
||||||
|
ONLY_ACTIVE_ARCH[config=Debug] = YES
|
||||||
|
DEBUG_INFORMATION_FORMAT[config=Debug] = dwarf
|
||||||
|
ENABLE_TESTABILITY[config=Debug] = YES
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL[config=Debug] = -Onone
|
||||||
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS[config=Debug] = DEBUG
|
||||||
|
SWIFT_COMPILATION_MODE[config=Debug] = singlefile
|
||||||
|
LLVM_LTO[config=Debug] = NO
|
||||||
|
DEAD_CODE_STRIPPING[config=Debug] = NO
|
||||||
|
VALIDATE_PRODUCT[config=Debug] = NO
|
||||||
|
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
#include "Framework.xcconfig"
|
|
||||||
|
|
||||||
SWIFT_INCLUDE_PATHS = $(PROJECT_DIR)/Configuration/Constants
|
|
||||||
GCC_PREPROCESSOR_DEFINITIONS = APP_BUNDLE_IDENTIFIER=$(APP_BUNDLE_IDENTIFIER) APP_GROUP_IDENTIFIER=$(APP_GROUP_IDENTIFIER) NETWORK_EXTENSION_BUNDLE_IDENTIFIER=$(NETWORK_EXTENSION_BUNDLE_IDENTIFIER)
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
#import <Foundation/Foundation.h>
|
|
||||||
|
|
||||||
#define MACRO_STRING_(m) #m
|
|
||||||
#define MACRO_STRING(m) @MACRO_STRING_(m)
|
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
|
||||||
|
|
||||||
static NSString * const AppBundleIdentifier = MACRO_STRING(APP_BUNDLE_IDENTIFIER);
|
|
||||||
static NSString * const AppGroupIdentifier = MACRO_STRING(APP_GROUP_IDENTIFIER);
|
|
||||||
static NSString * const NetworkExtensionBundleIdentifier = MACRO_STRING(NETWORK_EXTENSION_BUNDLE_IDENTIFIER);
|
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_END
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
@_implementationOnly import CConstants
|
|
||||||
import Foundation
|
|
||||||
import OSLog
|
|
||||||
|
|
||||||
public enum Constants {
|
|
||||||
enum Error: Swift.Error {
|
|
||||||
case invalidAppGroupIdentifier
|
|
||||||
}
|
|
||||||
|
|
||||||
public static let bundleIdentifier = AppBundleIdentifier
|
|
||||||
public static let appGroupIdentifier = AppGroupIdentifier
|
|
||||||
public static let networkExtensionBundleIdentifier = NetworkExtensionBundleIdentifier
|
|
||||||
|
|
||||||
public static var socketURL: URL {
|
|
||||||
get throws {
|
|
||||||
try groupContainerURL.appending(component: "burrow.sock", directoryHint: .notDirectory)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static var databaseURL: URL {
|
|
||||||
get throws {
|
|
||||||
try groupContainerURL.appending(component: "burrow.db", directoryHint: .notDirectory)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static var groupContainerURL: URL {
|
|
||||||
get throws { try _groupContainerURL.get() }
|
|
||||||
}
|
|
||||||
private static let _groupContainerURL: Result<URL, Error> = {
|
|
||||||
switch FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupIdentifier) {
|
|
||||||
case .some(let url): .success(url)
|
|
||||||
case .none:
|
|
||||||
fallbackContainerURL().mapError { _ in .invalidAppGroupIdentifier }
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
private static func fallbackContainerURL() -> Result<URL, any Swift.Error> {
|
|
||||||
#if targetEnvironment(simulator)
|
|
||||||
Result {
|
|
||||||
// The simulator app's Application Support path lives inside its sandbox container,
|
|
||||||
// so the host daemon cannot reach it. Use a shared host temp location instead.
|
|
||||||
let url = URL(filePath: "/tmp", directoryHint: .isDirectory)
|
|
||||||
.appending(component: bundleIdentifier, directoryHint: .isDirectory)
|
|
||||||
.appending(component: "SimulatorFallback", directoryHint: .isDirectory)
|
|
||||||
try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true)
|
|
||||||
return url
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
.failure(Error.invalidAppGroupIdentifier)
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension Logger {
|
|
||||||
@_dynamicReplacement(for: subsystem)
|
|
||||||
public static var subsystem: String { Constants.bundleIdentifier }
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
module CConstants {
|
|
||||||
header "Constants.h"
|
|
||||||
export *
|
|
||||||
}
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
// Release
|
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf-with-dsym
|
|
||||||
SWIFT_COMPILATION_MODE = wholemodule
|
|
||||||
SWIFT_OPTIMIZATION_LEVEL = -Osize
|
|
||||||
LLVM_LTO = YES
|
|
||||||
DEAD_CODE_STRIPPING = YES
|
|
||||||
STRIP_INSTALLED_PRODUCT = YES
|
|
||||||
STRIP_SWIFT_SYMBOLS = YES
|
|
||||||
COPY_PHASE_STRIP = NO
|
|
||||||
VALIDATE_PRODUCT = YES
|
|
||||||
ENABLE_MODULE_VERIFIER = YES
|
|
||||||
|
|
||||||
// Debug
|
|
||||||
ONLY_ACTIVE_ARCH[config=Debug] = YES
|
|
||||||
DEBUG_INFORMATION_FORMAT[config=Debug] = dwarf
|
|
||||||
ENABLE_TESTABILITY[config=Debug] = YES
|
|
||||||
GCC_PREPROCESSOR_DEFINITIONS[config=Debug] = DEBUG=1 $(inherited)
|
|
||||||
SWIFT_OPTIMIZATION_LEVEL[config=Debug] = -Onone
|
|
||||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS[config=Debug] = DEBUG
|
|
||||||
SWIFT_COMPILATION_MODE[config=Debug] = singlefile
|
|
||||||
LLVM_LTO[config=Debug] = NO
|
|
||||||
DEAD_CODE_STRIPPING[config=Debug] = NO
|
|
||||||
VALIDATE_PRODUCT[config=Debug] = NO
|
|
||||||
STRIP_INSTALLED_PRODUCT[config=Debug] = NO
|
|
||||||
STRIP_SWIFT_SYMBOLS[config=Debug] = NO
|
|
||||||
ENABLE_MODULE_VERIFIER[config=Debug] = NO
|
|
||||||
|
|
@ -1,6 +1,2 @@
|
||||||
LD_EXPORT_SYMBOLS = NO
|
|
||||||
|
|
||||||
OTHER_SWIFT_FLAGS = $(inherited) -Xfrontend -disable-autolink-framework -Xfrontend UIKit -Xfrontend -disable-autolink-framework -Xfrontend AppKit -Xfrontend -disable-autolink-framework -Xfrontend SwiftUI
|
|
||||||
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @executable_path/../../Frameworks
|
LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @executable_path/../../Frameworks
|
||||||
LD_RUNPATH_SEARCH_PATHS[sdk=macosx*] = $(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks
|
LD_RUNPATH_SEARCH_PATHS[sdk=macos*] = $(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks
|
||||||
|
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
PRODUCT_NAME = Burrow$(TARGET_NAME:c99extidentifier)
|
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = $(APP_BUNDLE_IDENTIFIER).$(TARGET_NAME:c99extidentifier)
|
|
||||||
APPLICATION_EXTENSION_API_ONLY = YES
|
|
||||||
SWIFT_INSTALL_OBJC_HEADER = NO
|
|
||||||
SWIFT_SKIP_AUTOLINKING_FRAMEWORKS = YES
|
|
||||||
SWIFT_SKIP_AUTOLINKING_LIBRARIES = YES
|
|
||||||
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @loader_path/Frameworks
|
|
||||||
LD_RUNPATH_SEARCH_PATHS[sdk=macosx*] = $(inherited) @executable_path/../Frameworks @loader_path/Frameworks
|
|
||||||
|
|
||||||
DYLIB_INSTALL_NAME_BASE = @rpath
|
|
||||||
DYLIB_COMPATIBILITY_VERSION = 1
|
|
||||||
DYLIB_CURRENT_VERSION = 1
|
|
||||||
VERSIONING_SYSTEM =
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
DEVELOPMENT_TEAM = P6PV2R9443
|
DEVELOPMENT_TEAM = 87PW93R2ZR
|
||||||
APP_BUNDLE_IDENTIFIER = com.hackclub.burrow
|
APP_BUNDLE_IDENTIFIER = com.hackclub.burrow
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,5 @@
|
||||||
<dict>
|
<dict>
|
||||||
<key>CFBundleName</key>
|
<key>CFBundleName</key>
|
||||||
<string>$(INFOPLIST_KEY_CFBundleDisplayName)</string>
|
<string>$(INFOPLIST_KEY_CFBundleDisplayName)</string>
|
||||||
<key>SUFeedURL</key>
|
|
||||||
<string>$(BURROW_SPARKLE_FEED_URL)</string>
|
|
||||||
<key>SUPublicEDKey</key>
|
|
||||||
<string>$(BURROW_SPARKLE_PUBLIC_ED_KEY)</string>
|
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
#include "Compiler.xcconfig"
|
|
||||||
|
|
||||||
SUPPORTED_PLATFORMS = iphonesimulator iphoneos
|
|
||||||
TARGETED_DEVICE_FAMILY[sdk=iphone*] = 1,2
|
|
||||||
|
|
||||||
PRODUCT_NAME = $(TARGET_NAME)
|
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = $(APP_BUNDLE_IDENTIFIER).uitests
|
|
||||||
|
|
||||||
STRING_CATALOG_GENERATE_SYMBOLS = NO
|
|
||||||
SWIFT_EMIT_LOC_STRINGS = NO
|
|
||||||
|
|
||||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @loader_path/Frameworks
|
|
||||||
TEST_TARGET_NAME = App
|
|
||||||