diff --git a/docs/github-actions/backup-theme-settings.yml b/docs/github-actions/backup-theme-settings.yml new file mode 100644 index 0000000..c66e7b6 --- /dev/null +++ b/docs/github-actions/backup-theme-settings.yml @@ -0,0 +1,60 @@ +name: Backup Theme Settings + +on: + schedule: # run the settings backup every hour + - cron: "0 */1 * * *" + workflow_dispatch: + +jobs: + backup: + runs-on: ubuntu-latest + env: + SHOPIFY_CLI_THEME_TOKEN: ${{ secrets.SHOPIFY_CLI_THEME_TOKEN }} + SHOPIFY_FLAG_STORE: ${{ vars.SHOPIFY_FLAG_STORE }} + SHOPIFY_FLAG_PATH: ${{ vars.SHOPIFY_FLAG_PATH }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SETTINGS_APPROVER: ${{ secrets.SETTINGS_APPROVER }} + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v3 + with: + node-version: "19" + cache: "yarn" + - uses: ruby/setup-ruby@v1 + with: + ruby-version: 3.2 + bundler: "latest" + - name: Install packages + run: yarn install + - name: Download published theme settings + run: npx shopkeeper theme settings download + - name: Store the settings + run: npx shopkeeper bucket save --bucket production + - name: Set up up git user + run: | + # Setup username and email + git config user.name "GitHub Actions Bot" + git config user.email "ops@thebeyondgroup.la" + - name: Store datetime + run: echo "NOW=$(date +"%Y-%m-%d-%H")" >> $GITHUB_ENV + - name: Store branch name + run: echo "NEW_BRANCH=github-action/settings-$NOW" >> $GITHUB_ENV + - name: Create PR + run: | + if [[ -z $(git status -s) ]] + then + echo "No changes. Nothing to commit" + else + gh label create settings-update --force + git checkout -b $NEW_BRANCH + git add . + git commit -m "Update theme settings as of $NOW" + git push origin $NEW_BRANCH + gh pr create --title "Update theme settings as of $NOW" --body "Update to latest theme settings"--label settings-update + # We can't approve the PR with same token that created it. + OLD_GITHUB_TOKEN=$GITHUB_TOKEN + GITHUB_TOKEN=$SETTINGS_APPROVER + gh pr review --approve + GITHUB_TOKEN=$OLD_GITHUB_TOKEN + gh pr merge --merge + fi diff --git a/docs/github-actions/blue-green.yml b/docs/github-actions/blue-green.yml new file mode 100644 index 0000000..5ee3267 --- /dev/null +++ b/docs/github-actions/blue-green.yml @@ -0,0 +1,40 @@ +name: Shopify Blue/Green Deploy + +# Controls when the action will run. +# Triggers the workflow on push or pull request events but only for the master branch +on: + push: + branches: [main] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +jobs: + deploy: + # The type of runner that the job will run on + runs-on: ubuntu-latest + env: + SHOPIFY_CLI_THEME_TOKEN: ${{ secrets.SHOPIFY_CLI_THEME_TOKEN }} + SHOPIFY_FLAG_STORE: ${{ vars.SHOPIFY_FLAG_STORE }} + SHOPIFY_FLAG_PATH: ${{ vars.SHOPIFY_FLAG_PATH }} + SKR_FLAG_BLUE_THEME_ID: ${{ secrets.SKR_FLAG_BLUE_THEME_ID }} + SKR_FLAG_GREEN_THEME_ID: ${{ secrets.SKR_FLAG_GREEN_THEME_ID }} + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v3 + with: + node-version: "19" + cache: "yarn" + - name: Install packages + run: yarn install + - name: Select theme settings + run: npx shopkeeper bucket restore --bucket production + - name: Build assets + run: yarn build:prod + - name: Deploy to on deck theme + uses: nick-fields/retry@v2 + with: + timeout_minutes: 10 + max_attempts: 3 + retry_on: error + command: npx shopkeeper theme deploy diff --git a/docs/github-actions/generate-preview-theme.yml b/docs/github-actions/generate-preview-theme.yml new file mode 100644 index 0000000..24f0314 --- /dev/null +++ b/docs/github-actions/generate-preview-theme.yml @@ -0,0 +1,64 @@ +name: Generate Preview + +on: + pull_request: + types: + - reopened + branches-ignore: + - "github-action/**" + push: + branches-ignore: + - "master" + - "github-action/**" + + workflow_dispatch: + +jobs: + preview: + runs-on: ubuntu-latest + env: + SHOPIFY_CLI_THEME_TOKEN: ${{ secrets.SHOPIFY_CLI_THEME_TOKEN }} + SHOPIFY_FLAG_STORE: ${{ vars.SHOPIFY_FLAG_STORE }} + SHOPIFY_FLAG_PATH: ${{ vars.SHOPIFY_FLAG_PATH }} + steps: + - uses: actions/checkout@v4 + - uses: rlespinasse/github-slug-action@v4 + with: + slug-maxlength: 50 # Shopify preview environment name cannot be more than 50 chars + - uses: actions/setup-node@v3 + with: + node-version: "19" + cache: "yarn" + - uses: 8BitJonny/gh-get-current-pr@2.2.0 + id: pr_status + with: + # Verbose setting SHA when using Pull_Request event trigger + sha: ${{ github.event.pull_request.head.sha }} + # Only return if PR is still open. (By default it returns PRs in any state.) + filterOutClosed: true + # Only return if PR is not in draft state. (By default it returns PRs in any state.) + filterOutDraft: true + - name: Install packages + run: yarn install + - name: Select theme settings + run: npx shopkeeper bucket restore --bucket production + - name: Build assets + run: yarn build:prod + - name: Create theme + uses: nick-fields/retry@v2 + with: + timeout_minutes: 10 + max_attempts: 3 + retry_on: error + command: npx shopkeeper theme create --theme ${{ env.GITHUB_REF_NAME_SLUG_URL }} + - name: Get theme ID + run: echo "THEME_ID=$(npx shopkeeper theme get --theme ${{ env.GITHUB_REF_NAME_SLUG_URL }})" >> $GITHUB_ENV + - name: Add preview link to PR + if: steps.pr_status.outputs.pr_found == 'true' + uses: unsplash/comment-on-pr@master + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + msg: | + **Preview:** [Storefront](https://${{ vars.SHOPIFY_FLAG_STORE }}?preview_theme_id=${{ env.THEME_ID }}) | [Admin](https://${{ vars.SHOPIFY_FLAG_STORE }}/admin/themes/${{ env.THEME_ID }}/editor) + delete_prev_regex_msg: "Preview:" # OPTIONAL diff --git a/docs/github-actions/sync-theme-changes.yml b/docs/github-actions/sync-theme-changes.yml new file mode 100644 index 0000000..811da5f --- /dev/null +++ b/docs/github-actions/sync-theme-changes.yml @@ -0,0 +1,141 @@ +name: Sync Theme Changes + +on: + schedule: # run the theme sync every hour + - cron: "0 */1 * * *" + workflow_dispatch: + +jobs: + sync: + runs-on: ubuntu-latest + env: + SHOPIFY_CLI_THEME_TOKEN: ${{ secrets.SHOPIFY_CLI_THEME_TOKEN }} + SHOPIFY_FLAG_STORE: ${{ vars.SHOPIFY_FLAG_STORE }} + SHOPIFY_FLAG_PATH: ${{ vars.SHOPIFY_FLAG_PATH }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v3 + with: + node-version: "20" + cache: "npm" + - name: Install Shopify CLI + run: npm install -g @shopify/cli + - name: Download all theme files from live theme + run: shopify theme pull --live --force + - name: Check for non-settings changes + id: check_changes + run: | + # Check if any files changed at all + if [[ -z $(git status --porcelain) ]]; then + echo "No changes detected" + echo "has_changes=false" >> $GITHUB_OUTPUT + exit 0 + fi + + # Use git pathspec to check only non-settings files + # Include: assets, layout, snippets, locales, *.liquid files + # Exclude: settings files (handled by backup-theme-settings workflow) + if git diff --quiet HEAD -- 'assets/*' 'layout/*' 'snippets/*' 'locales/*' 'sections/*.liquid' 'templates/*.liquid'; then + echo "Only settings files changed - these are handled by the backup-theme-settings workflow" + echo "has_changes=false" >> $GITHUB_OUTPUT + exit 0 + fi + + echo "Non-settings files changed" + echo "has_changes=true" >> $GITHUB_OUTPUT + + # Get changed non-settings files using git pathspec + NON_SETTINGS_CHANGES=$(git status --porcelain -- 'assets/*' 'layout/*' 'snippets/*' 'locales/*' 'sections/*.liquid' 'templates/*.liquid') + + # Count changes by type + ADDED=$(echo "$NON_SETTINGS_CHANGES" | grep '^A ' | wc -l || echo "0") + MODIFIED=$(echo "$NON_SETTINGS_CHANGES" | grep '^M ' | wc -l || echo "0") + DELETED=$(echo "$NON_SETTINGS_CHANGES" | grep '^D ' | wc -l || echo "0") + + echo "added_count=$ADDED" >> $GITHUB_OUTPUT + echo "modified_count=$MODIFIED" >> $GITHUB_OUTPUT + echo "deleted_count=$DELETED" >> $GITHUB_OUTPUT + + # Store changed files list for PR body + echo "CHANGED_FILES_LIST<> $GITHUB_ENV + echo "$NON_SETTINGS_CHANGES" >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + - name: Set up git user + if: steps.check_changes.outputs.has_changes == 'true' + run: | + git config user.name "GitHub Actions Bot" + git config user.email "ops@thebeyondgroup.la" + - name: Store datetime and branch name + if: steps.check_changes.outputs.has_changes == 'true' + run: | + echo "NOW=$(date +"%Y-%m-%d-%H")" >> $GITHUB_ENV + echo "NEW_BRANCH=github-action/theme-sync-$NOW" >> $GITHUB_ENV + - name: Create PR for theme changes + if: steps.check_changes.outputs.has_changes == 'true' + run: | + # Create label + gh label create theme-code-sync --color "D73A4A" --description "Theme code changes synced from Shopify" --force + + # Create branch + git checkout -b $NEW_BRANCH + + # Stage only non-settings files using git pathspec + git add -- 'assets/*' 'layout/*' 'snippets/*' 'locales/*' 'sections/*.liquid' 'templates/*.liquid' + + # Check if we have staged changes + if git diff --cached --quiet; then + echo "No non-settings changes to commit" + exit 0 + fi + + # Commit only the non-settings changes + ADDED="${{ steps.check_changes.outputs.added_count }}" + MODIFIED="${{ steps.check_changes.outputs.modified_count }}" + DELETED="${{ steps.check_changes.outputs.deleted_count }}" + + git commit -m "Sync theme code changes from Shopify ($ADDED added, $MODIFIED modified, $DELETED deleted) + + This commit contains non-settings theme file changes made directly in the Shopify admin. + Settings file changes are handled separately by the backup-theme-settings workflow. + + Changed files: + $CHANGED_FILES_LIST" + + git push origin $NEW_BRANCH + + # Create PR with detailed description + gh pr create \ + --title "Sync theme code changes from Shopify as of $NOW" \ + --body "## Theme Code Changes Detected + + This PR contains **non-settings** changes that were made directly in the Shopify admin (theme editor or code editor). + + **Summary:** + - 📁 Files added: $ADDED + - ✏️ Files modified: $MODIFIED + - 🗑️ Files deleted: $DELETED + + **Changed Files:** + \`\`\` + $CHANGED_FILES_LIST + \`\`\` + + > **Note:** Settings file changes (JSON templates, settings_data.json, section group JSON files) are handled separately by the \`backup-theme-settings\` workflow and will appear in separate PRs. + + **⚠️ Please review these changes carefully before merging.** + + These changes were made directly in Shopify and may include: + - Liquid template modifications + - Asset file changes (CSS, JS, images) + - Layout file updates + - Snippet changes + - Locale file updates + + Consider whether these changes should be: + - Merged as-is + - Modified to follow your coding standards + - Integrated into your existing development workflow" \ + --label theme-code-sync + + echo "✅ Created PR for theme code changes" diff --git a/docs/thinking.md b/docs/thinking.md new file mode 100644 index 0000000..be406ab --- /dev/null +++ b/docs/thinking.md @@ -0,0 +1,24 @@ +Shopify is the source of truth + +When a PR is opened, we + +- restore the production bucket +- build the code +- push the theme + +This has the effect of giving the preview theme the code that's in the repo. +Assuming the branch has been rebased recently, the settings will be fresh. + +When a PR is merged, we: + +- restore the production bucket +- build theme +- download the latest theme settings from live +- push the theme to the destination + +This means that the theme on shopify will contain the contents of `shopify` + +When settings sync runs, we: + +- download the latest theme settings files +- copy settings into the production bucket