Skip to content

Schedule social media posts #2450

Schedule social media posts

Schedule social media posts #2450

name: Schedule social media posts
on:
# Fire after Build and deploy finishes on master so posts only go out
# after the blog page is actually live. Posting on `push: master` raced
# the deploy and produced 404 link cards (especially sticky on Bluesky,
# which caches the first fetch of the og:image).
workflow_run:
workflows: ["Build and deploy"]
types: [completed]
branches: [master]
workflow_dispatch:
inputs:
dry_run:
description: "Dry run — scan + show what would post, no posting / no state write"
type: boolean
default: false
permissions:
id-token: write
contents: read
pull-requests: write
concurrency:
group: schedule-social
cancel-in-progress: false
jobs:
schedule-social:
if: |
github.repository == 'pulumi/docs' &&
(github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success')
name: Schedule social media posts
runs-on: ubuntu-latest
environment: production
env:
FAILURE_SUMMARY_FILE: /tmp/social-failure-summary.txt
outputs:
failure_summary: ${{ steps.failure-summary.outputs.summary }}
steps:
- name: Fetch secrets from ESC
id: esc-secrets
uses: pulumi/esc-action@v3
- uses: actions/checkout@v7
with:
fetch-depth: 0
# On workflow_run, pin to the SHA the deploy actually built. Default
# ref under workflow_run is master HEAD, which may have moved on.
ref: ${{ github.event.workflow_run.head_sha || github.sha }}
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v6
with:
role-to-assume: arn:aws:iam::388588623842:role/ContinuousDelivery
role-session-name: social-scheduling
aws-region: us-west-2
- uses: pulumi/actions@v7
- name: Get social state bucket name
id: bucket
env:
PULUMI_ACCESS_TOKEN: ${{ steps.esc-secrets.outputs.PULUMI_ACCESS_TOKEN }}
run: |
set -eo pipefail
BUCKET=$(pulumi -C infrastructure stack output socialStateBucketName --stack ${{ vars.PULUMI_STACK_NAME }})
echo "name=$BUCKET" >> "$GITHUB_OUTPUT"
- uses: astral-sh/setup-uv@v7
- name: Configure git auth for private social_core git-dep
env:
PULUMI_BOT_TOKEN: ${{ steps.esc-secrets.outputs.PULUMI_BOT_TOKEN }}
run: |
git config --global url."https://x-access-token:${PULUMI_BOT_TOKEN}@github.com/".insteadOf "https://github.com/"
- name: Validate upload-post.com API key
env:
UPLOAD_POST_API_KEY: ${{ steps.esc-secrets.outputs.UPLOAD_POST_API_KEY }}
run: |
if [ -z "$UPLOAD_POST_API_KEY" ]; then
echo "::error::UPLOAD_POST_API_KEY is empty — check ESC environment"
exit 1
fi
STATUS=$(curl -s -o /tmp/api-check.txt -w "%{http_code}" \
-H @- \
"https://api.upload-post.com/api/uploadposts/history" \
<<< "Authorization: Apikey $UPLOAD_POST_API_KEY")
if [ "$STATUS" != "200" ]; then
echo "::error::upload-post.com API key validation failed (HTTP $STATUS)"
cat /tmp/api-check.txt
exit 1
fi
echo "API key valid (HTTP 200)"
- name: Schedule social posts for new blog content
id: post
continue-on-error: true
env:
UPLOAD_POST_API_KEY: ${{ steps.esc-secrets.outputs.UPLOAD_POST_API_KEY }}
SOCIAL_STATE_BUCKET: ${{ steps.bucket.outputs.name }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DRY_RUN: ${{ inputs.dry_run || 'false' }}
run: uv run scripts/social/schedule-posts.py
- name: Capture failure summary
id: failure-summary
if: steps.post.outcome == 'failure'
run: |
if [ -f "$FAILURE_SUMMARY_FILE" ]; then
{
echo "summary<<EOF"
cat "$FAILURE_SUMMARY_FILE"
echo "EOF"
} >> "$GITHUB_OUTPUT"
fi
- name: Fail if posting step failed
if: steps.post.outcome == 'failure'
run: exit 1
notify:
if: failure() && github.repository == 'pulumi/docs'
name: Send slack notification
runs-on: ubuntu-latest
environment: production
needs: [schedule-social]
steps:
- name: Fetch secrets from ESC
id: esc-secrets
uses: pulumi/esc-action@v3
- name: Slack Notification
uses: docker://sholung/action-slack-notify:v2.3.0
env:
SLACK_CHANNEL: docs-ops
SLACK_COLOR: "#F54242"
SLACK_MESSAGE: "social media scheduling failure in pulumi/docs repo :meow_sad: ${{ needs.schedule-social.outputs.failure_summary && format('({0}) ', needs.schedule-social.outputs.failure_summary) || '' }}${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
SLACK_USERNAME: docsbot
SLACK_WEBHOOK: ${{ steps.esc-secrets.outputs.SLACK_WEBHOOK_URL }}
SLACK_ICON: https://www.pulumi.com/logos/brand/avatar-on-white.png
env:
ESC_ACTION_OIDC_AUTH: true
ESC_ACTION_OIDC_ORGANIZATION: pulumi
ESC_ACTION_OIDC_REQUESTED_TOKEN_TYPE: urn:pulumi:token-type:access_token:organization
ESC_ACTION_ENVIRONMENT: github-secrets/pulumi-docs
ESC_ACTION_EXPORT_ENVIRONMENT_VARIABLES: false