Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 138 additions & 4 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ on:
- opened # PR was open
- reopened # PR was closed and is now open again
- ready_for_review # PR was converted from draft to open
- closed # PR was closed

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
Expand Down Expand Up @@ -108,14 +109,147 @@ jobs:
HAPPO_API_KEY: ${{ secrets.HAPPO_API_KEY }}
HAPPO_API_SECRET: ${{ secrets.HAPPO_API_SECRET }}

deploy-docs:
deploy-storybook-preview:
if: ${{ github.event.pull_request.head.ref != 'changeset-release/master' }}
name: Deploy Picasso docs
name: Deploy Storybook Preview
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest not to change them, as they can be mentioned in some Grafana dashboards or some reports

runs-on: ubuntu-latest
permissions:
contents: read
contents: write
pull-requests: write
pages: write
id-token: write
needs: [static-checks]
steps:
- name: Checkout
uses: actions/checkout@v4

# Some new deployment process is needed here
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20.18

- name: Install dependencies from cache
uses: ./.github/actions/yarn-install

- name: Build Storybook
run: yarn build:storybook

- name: Checkout existing gh-pages content
id: checkout-gh-pages
uses: actions/checkout@v4
continue-on-error: true
with:
ref: gh-pages
path: gh-pages-content
token: ${{ secrets.GITHUB_TOKEN }}

- name: Create gh-pages directory if branch doesn't exist
if: steps.checkout-gh-pages.outcome == 'failure'
run: |
echo "🆕 gh-pages branch doesn't exist, creating empty directory structure"
mkdir -p gh-pages-content
echo "# Picasso Storybook" > gh-pages-content/README.md
echo "This directory contains Storybook deployments for Picasso." >> gh-pages-content/README.md

- name: Prepare preview deployment
run: |
# Create pr-{number} directory in existing gh-pages content
PR_DIR="gh-pages-content/pr-${{ github.event.pull_request.number }}"

# Remove existing PR directory if it exists
rm -rf "$PR_DIR"

# Create new PR directory and copy storybook build
mkdir -p "$PR_DIR"
cp -r build/storybook/* "$PR_DIR/"

echo "📂 Prepared preview in: $PR_DIR"
ls -la "$PR_DIR"

- name: Setup Pages
uses: actions/configure-pages@v4

- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: gh-pages-content

- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

- name: Comment on PR
uses: actions/github-script@v7
with:
script: |
const prNumber = '${{ github.event.pull_request.number }}';
const deployUrl = `https://toptal.github.io/picasso/pr-${prNumber}/`;

await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: '📖 **Storybook Preview**\n\n🚀 Your Storybook preview is ready: **[View Storybook](' + deployUrl + ')**\n\n📍 Preview URL: `' + deployUrl + '`\n\nThis preview is updated automatically when you push changes to this PR.'
});

cleanup-storybook-preview:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why we would even bother removing it if we use gh pages? 🤔

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because we need to update whole directory each time, if we will not clean it checkout and update time will grow. One thing I need to check about concurrency between parallel PRs and master when playing with gh-pages

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

got it 🤔 yeah, but this doesn't look reliable. Maybe we can have a separate workflow, that will be triggered on CRON? because this one can fail or something

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, need to test.

Regarding concurrency I'm will add concurrent group.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, I mean, imagine you close the PR and this workflow failed by some reason, timeout, ex. So PR temploy will be forever in the repo

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That could happen indeed, but let's see maybe it something we can fix down the road. For me right now what is important is multiple instances of docs (release, temploy) and concurrency.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can be solved by separate workflow run on cron schedule ☝️

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, separate workflow that reacts on: pr closed, cron job and can also be manually triggered.

if: ${{ github.event.action == 'closed' }}
name: Cleanup Storybook Preview
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
pages: write
id-token: write
steps:
- name: Checkout gh-pages branch
id: checkout-gh-pages-cleanup
uses: actions/checkout@v4
continue-on-error: true
with:
ref: gh-pages
path: gh-pages-content
token: ${{ secrets.GITHUB_TOKEN }}

- name: Create gh-pages directory if branch doesn't exist
if: steps.checkout-gh-pages-cleanup.outcome == 'failure'
run: |
echo "🆕 gh-pages branch doesn't exist, creating empty directory structure"
mkdir -p gh-pages-content
echo "# Picasso Storybook" > gh-pages-content/README.md
echo "This directory contains Storybook deployments for Picasso." >> gh-pages-content/README.md

- name: Remove PR preview directory
run: |
PR_DIR="gh-pages-content/pr-${{ github.event.pull_request.number }}"
if [ -d "$PR_DIR" ]; then
echo "🗑️ Removing preview directory: $PR_DIR"
rm -rf "$PR_DIR"
echo "Remaining content after cleanup:"
ls -la gh-pages-content/
else
echo "Preview directory $PR_DIR does not exist"
fi

- name: Setup Pages
uses: actions/configure-pages@v4

- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: gh-pages-content

- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

- name: Comment cleanup notification
uses: actions/github-script@v7
with:
script: |
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: '🗑️ **Storybook preview cleaned up**\n\nThe preview deployment has been automatically removed since this PR was closed.'
});
68 changes: 67 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ jobs:
contents: write
issues: write
pull-requests: write
pages: write
id-token: write
steps:
- name: Checkout Repo
uses: actions/checkout@v4
Expand Down Expand Up @@ -136,7 +138,71 @@ jobs:
payload: |
text: 'A new PR was merged to Picasso :parrotspin:'

# Implement Storybook deployment here
- name: Build Storybook for Production
if: ${{ success() && steps.changesets.outputs.published == 'true' }}
run: |
yarn build:storybook
echo "📖 Building Storybook for production deployment..." >> $GITHUB_STEP_SUMMARY

- name: Checkout existing gh-pages content
if: ${{ success() && steps.changesets.outputs.published == 'true' }}
id: checkout-gh-pages-release
uses: actions/checkout@v4
continue-on-error: true
with:
ref: gh-pages
path: gh-pages-content
token: ${{ secrets.GITHUB_TOKEN }}

- name: Create gh-pages directory if branch doesn't exist
if: ${{ success() && steps.changesets.outputs.published == 'true' && steps.checkout-gh-pages-release.outcome == 'failure' }}
run: |
echo "🆕 gh-pages branch doesn't exist, creating empty directory structure"
mkdir -p gh-pages-content
echo "# Picasso Storybook" > gh-pages-content/README.md
echo "This directory contains Storybook deployments for Picasso." >> gh-pages-content/README.md

- name: Prepare production deployment (preserve PR previews)
if: ${{ success() && steps.changesets.outputs.published == 'true' }}
run: |
# Backup PR preview directories
mkdir -p pr-backups
find gh-pages-content -maxdepth 1 -name "pr-*" -type d -exec cp -r {} pr-backups/ \; 2>/dev/null || true
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we have 2 separate directories: for PRs and for master? or we have to use only one?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems we can have only one but I can check would it simplify to have one more level with 2 directories

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simplified by introducing /prs directory so preview url will be prs/123


# Clear gh-pages content but preserve .git
find gh-pages-content -mindepth 1 -not -path "*/\.git*" -exec rm -rf {} + 2>/dev/null || true

# Copy new production build to root
cp -r build/storybook/* gh-pages-content/

# Restore PR preview directories
find pr-backups -maxdepth 1 -name "pr-*" -type d -exec cp -r {} gh-pages-content/ \; 2>/dev/null || true

echo "📂 Production content prepared, PR previews preserved"
echo "Content structure:"
ls -la gh-pages-content/

- name: Setup Pages
if: ${{ success() && steps.changesets.outputs.published == 'true' }}
uses: actions/configure-pages@v4

- name: Upload artifact
if: ${{ success() && steps.changesets.outputs.published == 'true' }}
uses: actions/upload-pages-artifact@v3
with:
path: gh-pages-content

- name: Deploy Production Storybook to GitHub Pages
if: ${{ success() && steps.changesets.outputs.published == 'true' }}
id: storybook-deployment
uses: actions/deploy-pages@v4

- name: Storybook Deployment Success
if: ${{ success() && steps.changesets.outputs.published == 'true' }}
run: |
echo "🚀 Production Storybook deployed to GitHub Pages!" >> $GITHUB_STEP_SUMMARY
echo "📖 Visit: https://toptal.github.io/picasso/" >> $GITHUB_STEP_SUMMARY
echo "✅ PR previews preserved during production deployment" >> $GITHUB_STEP_SUMMARY

integration-tests:
name: Integration Tests
Expand Down
Loading