diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 95c4c561..00000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,245 +0,0 @@ -name: CI -on: [push, pull_request] -jobs: - build: - name: Build & test - runs-on: ubuntu-latest - container: httptoolkit/act-build-base:v3.0.0 - steps: - - uses: actions/checkout@v3 - - # Install Node 14 - - uses: actions/setup-node@v3 - with: - node-version: 14 - cache: 'npm' - - - run: npm install -g npm@8.5.5 - - # Install & build & test: - - run: npm ci - - # Build without secrets for previews, in non-push cases: - - name: Build for preview - if: github.event_name != 'push' - run: npm run build - env: - NODE_ENV: development - - # Build with secrets for production, on push only: - - name: Build for production - if: github.event_name == 'push' - run: npm run build - env: - NODE_ENV: production - GATSBY_POSTHOG_KEY: ${{ secrets.GATSBY_POSTHOG_KEY }} - - - uses: actions/upload-artifact@v3 - with: - name: public - path: public/* - if-no-files-found: error - - - uses: actions/upload-artifact@v3 - with: - name: rss - path: public/rss.xml - if-no-files-found: error - - check-blog-changes: - name: Check for new blog posts to announce - if: github.event_name == 'push' - runs-on: ubuntu-latest - container: httptoolkit/act-build-base:v3.0.0 - needs: build - outputs: - new-blog-post: ${{ steps.detect-changes.outputs.new-blog-post }} - steps: - - uses: actions/checkout@v3 - - - uses: actions/download-artifact@v3 - with: - name: rss - path: local-rss - - - id: detect-changes - name: 'Check for RSS differences' - shell: bash - run: | - curl -f https://httptoolkit.com/rss.xml > remote-rss.xml - - sudo apt-get update && sudo apt-get install xmlstarlet - - LOCAL_POSTS=$(xmlstarlet sel -t -v '//rss/channel/item/link' local-rss/rss.xml) - REMOTE_POSTS=$(xmlstarlet sel -t -v '//rss/channel/item/link' remote-rss.xml) - - # Matches remote posts against each local post, excludes those matches, - # and returns the remaining lines (or nothing, if there are none): - NEW_POSTS=$(grep -vFxf <(echo "$REMOTE_POSTS") <(echo "$LOCAL_POSTS") || true) - - if [[ $(echo "$NEW_POSTS" | wc -l) -gt 1 ]]; then - echo "More than one new post found - something odd is happening, failing the job" - exit 1 - fi - - # Grab the slug (the last path chunk) from each URL: - NEW_POST_SLUGS=$(echo $NEW_POSTS | sed -E 's|.*/([^/]+)/?$|\1|') - - # Ensure the output is exactly an empty string, if not a post (trim newlines etc): - if [[ ! -z "$(echo "$NEW_POST_SLUGS" | tr -d '\n')" ]]; then - echo "New blog post: $NEW_POST_SLUGS" - echo "new-blog-post=$(echo $NEW_POST_SLUGS)" >> "$GITHUB_OUTPUT" - else - echo "No new blog posts" - echo "new-blog-post=" >> "$GITHUB_OUTPUT" - fi - - publish-docker: - name: Build & publish container to Docker Hub - if: github.event_name == 'push' && !startsWith(github.ref, 'refs/heads/dependabot/') - runs-on: ubuntu-latest - container: httptoolkit/act-build-base - needs: build - steps: - - uses: actions/checkout@v3 - - - uses: actions/download-artifact@v3 - with: - name: public - path: public - - - uses: docker/setup-buildx-action@v2 - - name: Login to DockerHub - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Extract Docker metadata - id: meta - uses: docker/metadata-action@v4 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - images: httptoolkit/website - tags: | - type=raw,value=prod,enable={{is_default_branch}} - type=raw,value=latest,enable={{is_default_branch}} - type=sha - - - name: Publish to Docker Hub - uses: docker/build-push-action@v4 - with: - context: . - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - - publish-scaleway: - name: Deploy to Scaleway - if: github.event_name == 'push' && github.ref == 'refs/heads/main' - runs-on: ubuntu-latest - container: httptoolkit/act-build-base:v3.0.0 - needs: publish-docker - steps: - - name: Redeploy container - uses: thibaultchazal/scaleway-serverless-container-deploy-action@0d290edda0c3359e51442bd8bf730eafef4e290f - with: - container_id: ${{ vars.SCW_API_CONTAINER_ID }} - secret_key: ${{ secrets.SCW_SECRET_KEY }} - registry_image_url: "registry.hub.docker.com/httptoolkit/website:prod" - - - name: Flush CDN cache - run: | - # Wait a little - the reploy command doesn't wait for the container to start up - sleep 30 - - # Clear CDN cache to re-request content: - curl -f --request POST \ - --url https://api.bunny.net/pullzone/$PULL_ZONE_ID/purgeCache \ - --header "AccessKey: $BUNNY_SITE_API_KEY" - env: - PULL_ZONE_ID: 960393 - BUNNY_SITE_API_KEY: ${{ secrets.BUNNY_SITE_API_KEY }} - - announce-blog-changes: - name: Announce new blog posts - if: github.event_name == 'push' && github.ref == 'refs/heads/main' && needs.check-blog-changes.outputs.new-blog-post != '' - runs-on: ubuntu-latest - container: httptoolkit/act-build-base:v3.0.0 - needs: - - check-blog-changes - - publish-scaleway - steps: - - uses: actions/checkout@v3 - - - name: Get title & content for the changed post - id: read-post - run: | - SLUG="${{ needs.check-blog-changes.outputs.new-blog-post }}" - MARKDOWN=$(cat "src/posts/$SLUG.md") - FRONTMATTER=$(echo $MARKDOWN | sed -n '/^---$/,/^---$/p') - - # Get the title - stripping any surrounding quotes if required - TITLE=$(echo $FRONTMATTER | - sed -n 's/^title: //p' | - sed 's/^"//; s/"$//' | - sed "s/^'//; s/'$//" - ) - echo "::set-output name=title::$TITLE" - - # Get the post content, stripping out frontmatter: - CONTENT=$(echo $MARKDOWN | sed '0,/^---$/d; 0,/^---$/d') - echo "::set-output name=content::$CONTENT" - - URL="https://httptoolkit.com/blog/$SLUG/" - echo "::set-output name=url::$URL" - - - name: Log the results for debugging - run: | - echo "Title: ${{ steps.read-post.outputs.title }}" - echo "URL: ${{ steps.read-post.outputs.url }}" - echo "Content: ${{ steps.read-post.outputs.content }}" - - - name: Send an email about the new blog post with Mailcoach - run: | - API_ENDPOINT="https://http-toolkit.mailcoach.app/api/campaigns" - - # Create a Mailcoach campaign for this blog post email: - CAMPAIGN_ID=$(curl - -f - -X POST $API_ENDPOINT - -H "Authorization: Bearer $MAILCOACH_TOKEN" - -H 'Accept: application/json' - -H 'Content-Type: application/json' - -d '{ - "name": "Blog post: ${{ steps.read-post.outputs.title }}", - "email_list_uuid": "'$MAILING_LIST_UUID'", - "template_uuid": "'$EMAIL_TEMPLATE_ID'", - "fields": [ - { - "title": "${{ steps.read-post.outputs.title }}", - "content": "${{ steps.read-post.outputs.content }}", - "url": "${{ steps.read-post.outputs.url }}" - } - ] - }' - ) - - # Send a test email with this content immediately: - curl -f -X POST "$API_ENDPOINT/$CAMPAIGN_ID/send-test" \ - -H "Authorization: Bearer $MAILCOACH_TOKEN" \ - -H 'Accept: application/json' \ - -H 'Content-Type: application/json' \ - -d '{"email":"'$TEST_EMAIL'"}' - - # Schedule the email to send in 3 hours: - curl -X PUT "$API_ENDPOINT/$CAMPAIGN_ID" \ - -H "Authorization: Bearer $MAILCOACH_TOKEN" \ - -H 'Accept: application/json' \ - -H 'Content-Type: application/json' \ - -d '{"schedule_at":"'$(date -u -d "3 hours" +"%Y-%m-%d %H:%M:%S")'"}' - env: - MAILCOACH_TOKEN: ${{ secrets.MAILCOACH_TOKEN }} - EMAIL_TEMPLATE_ID: ${{ vars.BLOG_POST_EMAIL_TEMPLATE_ID }} - MAILING_LIST_UUID: ${{ vars.BLOG_POST_MAILING_LIST_UUID }} - TEST_EMAIL: ${{ vars.BLOG_POST_TEST_EMAIL }} \ No newline at end of file diff --git a/.github/workflows/test-job.yml b/.github/workflows/test-job.yml new file mode 100644 index 00000000..808fbff4 --- /dev/null +++ b/.github/workflows/test-job.yml @@ -0,0 +1,110 @@ +name: "WIP: Test RSS check job" +on: [push] +jobs: + check-blog-changes: + name: Check for new blog posts to announce + runs-on: ubuntu-latest + container: httptoolkit/act-build-base:v3.0.0 + outputs: + new-blog-post: ${{ steps.detect-changes.outputs.new-blog-post }} + steps: + - id: detect-changes + name: 'Check for RSS differences' + run: | + echo "new-blog-post=debug-failing-docker-container" >> "$GITHUB_OUTPUT" + + announce-blog-changes: + name: Announce new blog posts + if: github.event_name == 'push' && needs.check-blog-changes.outputs.new-blog-post != '' + runs-on: ubuntu-latest + container: httptoolkit/act-build-base:v3.0.0 + needs: + - check-blog-changes + steps: + - uses: actions/checkout@v3 + + - name: Get title & content for the changed post + id: read-post + run: | + SLUG="${{ needs.check-blog-changes.outputs.new-blog-post }}" + MARKDOWN=$(cat "src/posts/$SLUG.md") + FRONTMATTER=$(echo $MARKDOWN | sed -n '/^---$/,/^---$/p') + + # Get the title - stripping any surrounding quotes if required + TITLE=$(echo $FRONTMATTER | + sed -n 's/^title: //p' | + sed 's/^"//; s/"$//' | + sed "s/^'//; s/'$//" + ) + echo "title=$TITLE" >> "$GITHUB_OUTPUT" + + echo "title is $TITLE" + + URL="https://httptoolkit.com/blog/$SLUG/" + echo "url=$URL" >> "$GITHUB_OUTPUT" + + echo "URL is $URL" + + # Get the post content, stripping out frontmatter: + CONTENT=$(echo $MARKDOWN | sed '0,/^---$/d; 0,/^---$/d') + { + echo 'content<> "$GITHUB_OUTPUT" + + echo "Content is $CONTENT" + + echo 'GH OUTPUT is:' + + cat "$GITHUB_OUTPUT" + + - name: Log the results for debugging + run: | + echo "Title: ${{ steps.read-post.outputs.title }}" + echo "URL: ${{ steps.read-post.outputs.url }}" + echo "Content: ${{ steps.read-post.outputs.content }}" + + - name: Send an email about the new blog post with Mailcoach + run: | + API_ENDPOINT="https://http-toolkit.mailcoach.app/api/campaigns" + + # Create a Mailcoach campaign for this blog post email: + CAMPAIGN_ID=$(curl + -f + -X POST $API_ENDPOINT + -H "Authorization: Bearer $MAILCOACH_TOKEN" + -H 'Accept: application/json' + -H 'Content-Type: application/json' + -d '{ + "name": "Blog post: ${{ steps.read-post.outputs.title }}", + "email_list_uuid": "'$MAILING_LIST_UUID'", + "template_uuid": "'$EMAIL_TEMPLATE_ID'", + "fields": [ + { + "title": "${{ steps.read-post.outputs.title }}", + "content": "${{ steps.read-post.outputs.content }}", + "url": "${{ steps.read-post.outputs.url }}" + } + ] + }' + ) + + # Send a test email with this content immediately: + curl -f -X POST "$API_ENDPOINT/$CAMPAIGN_ID/send-test" \ + -H "Authorization: Bearer $MAILCOACH_TOKEN" \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -d '{"email":"'$TEST_EMAIL'"}' + + # Schedule the email to send in 3 hours: + curl -X PUT "$API_ENDPOINT/$CAMPAIGN_ID" \ + -H "Authorization: Bearer $MAILCOACH_TOKEN" \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -d '{"schedule_at":"'$(date -u -d "3 hours" +"%Y-%m-%d %H:%M:%S")'"}' + env: + MAILCOACH_TOKEN: ${{ secrets.MAILCOACH_TOKEN }} + EMAIL_TEMPLATE_ID: ${{ vars.BLOG_POST_EMAIL_TEMPLATE_ID }} + MAILING_LIST_UUID: ${{ vars.BLOG_POST_MAILING_LIST_UUID }} + TEST_EMAIL: ${{ vars.BLOG_POST_TEST_EMAIL }} \ No newline at end of file