Scheduled SEO Tasks #67
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Scheduled SEO Tasks | |
| on: | |
| schedule: | |
| # Run daily at 2 AM UTC | |
| - cron: '0 2 * * *' | |
| workflow_dispatch: | |
| jobs: | |
| # ========================================= | |
| # Health Check - Skip if site not deployed | |
| # ========================================= | |
| health-check: | |
| name: Check Site Availability | |
| runs-on: ubuntu-latest | |
| outputs: | |
| site_available: ${{ steps.check.outputs.available }} | |
| steps: | |
| - name: Check if production site is available | |
| id: check | |
| run: | | |
| HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://synthstack.app/ --max-time 30 || echo "000") | |
| echo "HTTP Status: $HTTP_STATUS" | |
| if [ "$HTTP_STATUS" = "200" ] || [ "$HTTP_STATUS" = "301" ] || [ "$HTTP_STATUS" = "302" ]; then | |
| echo "available=true" >> $GITHUB_OUTPUT | |
| echo "Site is available (HTTP $HTTP_STATUS)" | |
| else | |
| echo "available=false" >> $GITHUB_OUTPUT | |
| echo "Site is not available (HTTP $HTTP_STATUS) - skipping SEO tasks" | |
| fi | |
| # ========================================= | |
| # Generate & Submit Sitemap | |
| # ========================================= | |
| sitemap: | |
| name: Update Sitemap | |
| runs-on: ubuntu-latest | |
| needs: health-check | |
| if: needs.health-check.outputs.site_available == 'true' | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Install pnpm | |
| uses: pnpm/action-setup@v3 | |
| with: | |
| version: 9 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| cache: 'pnpm' | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Generate Sitemap | |
| run: pnpm --filter @synthstack/web generate:sitemap | |
| continue-on-error: true | |
| - name: Submit to Google Search Console | |
| run: | | |
| curl -s "https://www.google.com/ping?sitemap=https://synthstack.app/sitemap.xml" || true | |
| - name: Submit to Bing Webmaster | |
| run: | | |
| curl -s "https://www.bing.com/ping?sitemap=https://synthstack.app/sitemap.xml" || true | |
| - name: Submit to Yandex | |
| run: | | |
| curl -s "https://webmaster.yandex.com/ping?sitemap=https://synthstack.app/sitemap.xml" || true | |
| # ========================================= | |
| # Check Broken Links | |
| # ========================================= | |
| link-check: | |
| name: Check Broken Links | |
| runs-on: ubuntu-latest | |
| needs: health-check | |
| if: needs.health-check.outputs.site_available == 'true' | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Check for Broken Links | |
| uses: lycheeverse/lychee-action@v1 | |
| with: | |
| args: --verbose --no-progress 'https://synthstack.app/**/*.html' | |
| fail: false | |
| - name: Create Issue on Broken Links | |
| if: env.lychee_exit_code != 0 | |
| uses: peter-evans/create-issue-from-file@v5 | |
| with: | |
| title: Broken Links Detected | |
| content-filepath: ./lychee/out.md | |
| labels: seo, bug | |
| # ========================================= | |
| # Performance & SEO Audit | |
| # ========================================= | |
| lighthouse: | |
| name: Lighthouse Audit | |
| runs-on: ubuntu-latest | |
| needs: health-check | |
| if: needs.health-check.outputs.site_available == 'true' | |
| continue-on-error: true | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Run Lighthouse | |
| uses: treosh/lighthouse-ci-action@v11 | |
| with: | |
| urls: | | |
| https://synthstack.app | |
| https://synthstack.app/features | |
| https://synthstack.app/pricing | |
| https://synthstack.app/about | |
| https://synthstack.app/blog | |
| budgetPath: ./apps/web/lighthouse-budget.json | |
| uploadArtifacts: true | |
| temporaryPublicStorage: true | |
| - name: Check Performance Scores | |
| run: | | |
| # Parse lighthouse results and alert if scores drop below threshold | |
| echo "Lighthouse audit complete" | |
| # ========================================= | |
| # Monitor Core Web Vitals | |
| # ========================================= | |
| web-vitals: | |
| name: Check Core Web Vitals | |
| runs-on: ubuntu-latest | |
| needs: health-check | |
| if: needs.health-check.outputs.site_available == 'true' | |
| continue-on-error: true | |
| steps: | |
| - name: Check PageSpeed Insights | |
| run: | | |
| # Check key pages via PageSpeed Insights API | |
| if [ -n "${{ secrets.GOOGLE_API_KEY }}" ]; then | |
| curl -s "https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=https://synthstack.app&strategy=mobile&key=${{ secrets.GOOGLE_API_KEY }}" | jq '.lighthouseResult.categories.performance.score' || echo "PageSpeed check skipped" | |
| else | |
| echo "GOOGLE_API_KEY not set - skipping PageSpeed Insights check" | |
| fi | |
| # ========================================= | |
| # Summary Job | |
| # ========================================= | |
| summary: | |
| name: SEO Tasks Summary | |
| runs-on: ubuntu-latest | |
| needs: [health-check, sitemap, link-check, lighthouse, web-vitals] | |
| if: always() | |
| steps: | |
| - name: Report Status | |
| run: | | |
| echo "## SEO Tasks Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| if [ "${{ needs.health-check.outputs.site_available }}" = "true" ]; then | |
| echo "Site was available - SEO tasks executed" >> $GITHUB_STEP_SUMMARY | |
| echo "- Sitemap: ${{ needs.sitemap.result }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- Link Check: ${{ needs.link-check.result }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- Lighthouse: ${{ needs.lighthouse.result }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- Web Vitals: ${{ needs.web-vitals.result }}" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "Site was NOT available (503/unreachable) - SEO tasks skipped" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "This is expected if the production site is not yet deployed." >> $GITHUB_STEP_SUMMARY | |
| fi |