name: 'Skyscraper'
description: 'Delete old posts from Bluesky and Mastodon'
branding:
icon: 'trash-2'
color: 'blue'
inputs:
version:
description: 'Skyscraper version to use (e.g. "v0.1.0"). Defaults to latest.'
required: false
default: 'latest'
retention-days:
description: 'Delete posts older than this many days (default: 180)'
required: false
default: '180'
dry-run:
description: 'Set to "true" to preview deletions without actually deleting'
required: false
default: 'false'
delete-pinned:
description: 'Set to "true" to also delete pinned posts (default: skip them)'
required: false
default: 'false'
bluesky-identifier:
description: 'Bluesky handle or DID'
required: false
bluesky-app-password:
description: 'Bluesky app password'
required: false
bluesky-pds-host:
description: 'Bluesky PDS host URL'
required: false
default: 'https://bsky.social'
mastodon-instance-url:
description: 'Mastodon instance URL (e.g. https://mastodon.social)'
required: false
mastodon-access-token:
description: 'Mastodon access token'
required: false
keep:
description: |
Multiline list of posts to protect from deletion.
One entry per line, e.g. "bluesky:abc123". Lines starting with # are ignored.
required: false
keep-path:
description: 'Path to a keep file. Merged with keep input if both set.'
required: false
runs:
using: 'composite'
steps:
- name: Detect platform
id: detect
shell: bash
run: |
OS=$(uname -s)
ARCH=$(uname -m)
case "$OS" in
Linux)
case "$ARCH" in
x86_64) TARGET="x86_64-unknown-linux-gnu" ;;
aarch64) TARGET="aarch64-unknown-linux-gnu" ;;
*) echo "::error::Unsupported architecture: $ARCH"; exit 1 ;;
esac
EXT="tar.xz"
;;
Darwin)
case "$ARCH" in
x86_64) TARGET="x86_64-apple-darwin" ;;
arm64) TARGET="aarch64-apple-darwin" ;;
*) echo "::error::Unsupported architecture: $ARCH"; exit 1 ;;
esac
EXT="tar.xz"
;;
*)
echo "::error::Unsupported OS: $OS"
exit 1
;;
esac
echo "target=$TARGET" >> "$GITHUB_OUTPUT"
echo "ext=$EXT" >> "$GITHUB_OUTPUT"
- name: Download skyscraper
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
TARGET="${{ steps.detect.outputs.target }}"
EXT="${{ steps.detect.outputs.ext }}"
VERSION="${{ inputs.version }}"
REPO="ZacSweers/skyscraper"
if [ "$VERSION" = "latest" ]; then
TAG=$(gh release view --repo "$REPO" --json tagName -q .tagName)
else
TAG="$VERSION"
fi
ASSET="skyscraper-cli-${TARGET}.${EXT}"
TEMP_DIR=$(mktemp -d)
gh release download "$TAG" --repo "$REPO" --pattern "$ASSET" --dir "$TEMP_DIR"
mkdir -p "$TEMP_DIR/extracted"
tar -xf "$TEMP_DIR/$ASSET" -C "$TEMP_DIR/extracted" --strip-components=1
chmod +x "$TEMP_DIR/extracted/skyscraper"
mkdir -p "$HOME/.skyscraper/bin"
cp "$TEMP_DIR/extracted/skyscraper" "$HOME/.skyscraper/bin/"
echo "$HOME/.skyscraper/bin" >> "$GITHUB_PATH"
- name: Prepare keep file
id: keep
shell: bash
run: |
KEEP_CONTENT='${{ inputs.keep }}'
KEEP_PATH='${{ inputs.keep-path }}'
FINAL_PATH=""
# If inline content provided, write it to a temp file
if [ -n "$KEEP_CONTENT" ]; then
TEMP_FILE=$(mktemp)
printf '%s\n' "$KEEP_CONTENT" > "$TEMP_FILE"
# Append from path if also provided
if [ -n "$KEEP_PATH" ] && [ -f "$KEEP_PATH" ]; then
echo "" >> "$TEMP_FILE"
cat "$KEEP_PATH" >> "$TEMP_FILE"
fi
FINAL_PATH="$TEMP_FILE"
elif [ -n "$KEEP_PATH" ]; then
FINAL_PATH="$KEEP_PATH"
fi
echo "path=$FINAL_PATH" >> "$GITHUB_OUTPUT"
- name: Run skyscraper
shell: bash
run: skyscraper
env:
RUST_LOG: info
RETENTION_DAYS: ${{ inputs.retention-days }}
DRY_RUN: ${{ inputs.dry-run }}
DELETE_PINNED: ${{ inputs.delete-pinned }}
KEEP_FILE: ${{ steps.keep.outputs.path }}
BLUESKY_IDENTIFIER: ${{ inputs.bluesky-identifier }}
BLUESKY_APP_PASSWORD: ${{ inputs.bluesky-app-password }}
BLUESKY_PDS_HOST: ${{ inputs.bluesky-pds-host }}
MASTODON_INSTANCE_URL: ${{ inputs.mastodon-instance-url }}
MASTODON_ACCESS_TOKEN: ${{ inputs.mastodon-access-token }}