@softlimit/theme-envy 0.1.8-alpha → 0.1.11-alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/build/requires/templates.js +8 -0
- package/helpers/functions/deploy/README.md +19 -0
- package/helpers/functions/deploy/build-promise.js +14 -0
- package/helpers/functions/deploy/duplicate-live-theme.js +96 -0
- package/helpers/functions/deploy/env.js +5 -0
- package/helpers/functions/deploy/index.js +46 -0
- package/helpers/functions/deploy/push-theme.js +32 -0
- package/index.js +9 -0
- package/init/functions/copy-starter-config-files/.github/workflows/deploy.yml +53 -0
- package/init/functions/copy-starter-config-files/index.js +7 -0
- package/init/functions/copy-starter-config-files/utils/post-deploy.js +9 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -107,6 +107,7 @@ Commands:
|
|
|
107
107
|
build [options] [env] Build Shopify theme
|
|
108
108
|
clean Empty output directory
|
|
109
109
|
convert [options] [source] Convert an existing Shopify theme to Theme Envy directory structure
|
|
110
|
+
deploy Deploy your theme to Shopify by copying the live theme then pushing changes to codebase on top of it
|
|
110
111
|
dev Start development process and sync with Shopify using the Shopify CLI
|
|
111
112
|
find-orphans Find unused snippets, partials, and assets in your Shopify theme
|
|
112
113
|
init [options] [source] Initialize a new Shopify theme project with Theme Envy directory structure
|
|
@@ -14,6 +14,14 @@ const templateOutputPath = path.resolve(ThemeEnvy.outputPath, 'templates')
|
|
|
14
14
|
fs.ensureDirSync(templateOutputPath)
|
|
15
15
|
globbedTemplates.forEach(file => {
|
|
16
16
|
// write each file to dist
|
|
17
|
+
// if the file path includes customers, output into a customers directory in templates
|
|
18
|
+
if (file.includes('customers')) {
|
|
19
|
+
const customerOutputPath = path.resolve(templateOutputPath, 'customers')
|
|
20
|
+
fs.ensureDirSync(customerOutputPath)
|
|
21
|
+
fs.copyFileSync(file, path.resolve(customerOutputPath, path.basename(file)))
|
|
22
|
+
ThemeEnvy.progress.increment('templates', 1)
|
|
23
|
+
return
|
|
24
|
+
}
|
|
17
25
|
fs.copyFileSync(file, path.resolve(templateOutputPath, path.basename(file)))
|
|
18
26
|
// update progress bar
|
|
19
27
|
ThemeEnvy.progress.increment('templates', 1)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# CI/CD with Github Workflow
|
|
2
|
+
|
|
3
|
+
During the `init` command, Theme Envy copies a `deploy.yml` workflow file into your project. This file is used to build and deploy your project to Github Pages.
|
|
4
|
+
|
|
5
|
+
## Variable and Secret Requirements
|
|
6
|
+
|
|
7
|
+
This workflow requires one environment secret to be set in your Github repository settings.
|
|
8
|
+
|
|
9
|
+
First, set up a 'production' environment for this workflow to run in.
|
|
10
|
+
|
|
11
|
+
Next, install Theme Access in your store and create a new theme access token.
|
|
12
|
+
|
|
13
|
+
Save this access token as an environment secret called `SHOPIFY_CLI_THEME_TOKEN`.
|
|
14
|
+
|
|
15
|
+
## Triggering the workflow
|
|
16
|
+
|
|
17
|
+
The deploy workflow is triggered by any added tag that starts with `v`. This is usually done when you create a new release.
|
|
18
|
+
|
|
19
|
+
For testing purposes, it will also run on any push to a branch named `deploy-release-action`.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
const themeBuild = require(path.resolve(__dirname, '../../../build/index.js'))
|
|
3
|
+
const themeClean = require('../dist-clean.js')
|
|
4
|
+
|
|
5
|
+
module.exports = function(newThemeID) {
|
|
6
|
+
themeClean()
|
|
7
|
+
const promise = new Promise((resolve, reject) => {
|
|
8
|
+
themeBuild()
|
|
9
|
+
ThemeEnvy.events.on('build:complete', () => {
|
|
10
|
+
resolve(newThemeID)
|
|
11
|
+
})
|
|
12
|
+
})
|
|
13
|
+
return promise
|
|
14
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Exports function: duplicateLiveTheme
|
|
3
|
+
Returns a promise that resolves to the new theme ID
|
|
4
|
+
*/
|
|
5
|
+
const { spawn } = require('child_process')
|
|
6
|
+
const path = require('path')
|
|
7
|
+
const env = require('./env.js')
|
|
8
|
+
process.env.SHOPIFY_CLI_THEME_TOKEN = env.password
|
|
9
|
+
process.env.SHOPIFY_FLAG_STORE = ThemeEnvy.store
|
|
10
|
+
const dist = path.resolve(process.cwd(), ThemeEnvy.outputPath)
|
|
11
|
+
|
|
12
|
+
module.exports = async ({ themeName, type = 'unpublished' }) => {
|
|
13
|
+
/*
|
|
14
|
+
Download live theme from shopify to dist folder
|
|
15
|
+
*/
|
|
16
|
+
const _downloadLiveTheme = async () => {
|
|
17
|
+
console.log('Downloading Live Theme')
|
|
18
|
+
return new Promise((resolve, reject) => {
|
|
19
|
+
try {
|
|
20
|
+
const pull = spawn('shopify', ['theme', 'pull', '--live', '--path=' + dist], {
|
|
21
|
+
stdio: 'inherit'
|
|
22
|
+
})
|
|
23
|
+
pull.on('close', resolve)
|
|
24
|
+
|
|
25
|
+
const handleError = (error) => {
|
|
26
|
+
console.log(error)
|
|
27
|
+
reject(error)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
pull.on('error', handleError)
|
|
31
|
+
} catch (error) {
|
|
32
|
+
const err = new Error('Could not download live theme')
|
|
33
|
+
reject(err)
|
|
34
|
+
throw err
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// push without context templates first
|
|
40
|
+
const _shopifyNewTheme = async () => {
|
|
41
|
+
console.log(`Creating Theme: ${themeName}`)
|
|
42
|
+
return new Promise((resolve, reject) => {
|
|
43
|
+
try {
|
|
44
|
+
const push = spawn('shopify', ['theme', 'push', '--ignore=templates/\*.context.\*.json', '--ignore=sections/\*.context.\*.json', `--${type}`, '--json', (type === 'unpublished' && ('--theme=' + themeName)), '--path=' + dist])
|
|
45
|
+
push.stdout.setEncoding('utf8')
|
|
46
|
+
push.stdout.on('data', data => {
|
|
47
|
+
console.log(data)
|
|
48
|
+
if (data.includes('{"theme":')) {
|
|
49
|
+
// extract theme id from data
|
|
50
|
+
const themeID = data.match(/"id":(\d+)/)[1]
|
|
51
|
+
resolve(themeID)
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
const handleError = (error) => {
|
|
55
|
+
reject(error)
|
|
56
|
+
}
|
|
57
|
+
push.stderr.on('data', handleError)
|
|
58
|
+
push.on('error', handleError)
|
|
59
|
+
} catch {
|
|
60
|
+
throw new Error('Could not create new theme')
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// then do another push to the same theme and only push context templates
|
|
66
|
+
const _pushAdditionalTemplates = async (themeId) => {
|
|
67
|
+
console.log(`Updating additional templates on theme: ${themeId}`)
|
|
68
|
+
return new Promise((resolve, reject) => {
|
|
69
|
+
try {
|
|
70
|
+
const push = spawn('shopify', ['theme', 'push', '--only=templates/\*.context.\*.json', '--only=sections/\*.context.\*.json', '--json', '--theme=' + themeId, '--path=' + dist])
|
|
71
|
+
push.stdout.setEncoding('utf8')
|
|
72
|
+
push.stdout.on('data', data => {
|
|
73
|
+
console.log(data)
|
|
74
|
+
if (data.includes('{"theme":')) {
|
|
75
|
+
// extract theme id from data
|
|
76
|
+
const themeID = data.match(/"id":(\d+)/)[1]
|
|
77
|
+
resolve(themeID)
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
} catch {
|
|
81
|
+
throw new Error('Could not push to new theme')
|
|
82
|
+
}
|
|
83
|
+
})
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/*
|
|
87
|
+
do everything
|
|
88
|
+
*/
|
|
89
|
+
return _downloadLiveTheme()
|
|
90
|
+
.then(_shopifyNewTheme)
|
|
91
|
+
.then(themeId => _pushAdditionalTemplates(themeId))
|
|
92
|
+
.catch((err) => {
|
|
93
|
+
console.error(err.toString())
|
|
94
|
+
throw new Error('Theme download/backup failed')
|
|
95
|
+
})
|
|
96
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description theme-envy deploy duplicates the live theme, then pushes a build of the current theme to that new theme
|
|
3
|
+
* @example npx theme-envy deploy
|
|
4
|
+
* @returns {Void}
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const path = require('path')
|
|
8
|
+
const fs = require('fs')
|
|
9
|
+
const packageSettings = require(path.resolve(process.cwd(), 'package.json'))
|
|
10
|
+
const duplicateLiveTheme = require('./duplicate-live-theme')
|
|
11
|
+
const buildPromise = require('./build-promise')
|
|
12
|
+
const pushTheme = require('./push-theme')
|
|
13
|
+
const themeClean = require('../dist-clean')
|
|
14
|
+
const themeName = `${packageSettings.version} ${packageSettings.description}`
|
|
15
|
+
|
|
16
|
+
module.exports = function() {
|
|
17
|
+
// clean the dist directory
|
|
18
|
+
themeClean()
|
|
19
|
+
|
|
20
|
+
// duplicate live theme into output path
|
|
21
|
+
duplicateLiveTheme({ themeName })
|
|
22
|
+
|
|
23
|
+
// build theme from src
|
|
24
|
+
.then(buildPromise)
|
|
25
|
+
|
|
26
|
+
// push theme to new theme id
|
|
27
|
+
.then(pushTheme)
|
|
28
|
+
|
|
29
|
+
// get the theme id from the pushed theme and run post deploy scripts
|
|
30
|
+
.then(themeID => {
|
|
31
|
+
const postDeployPath = path.resolve(process.cwd(), 'utils/post-deploy.js')
|
|
32
|
+
if (fs.existsSync(postDeployPath)) {
|
|
33
|
+
const postDeploy = require(postDeployPath)
|
|
34
|
+
postDeploy({ themeName, themeID })
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// all done, log that the deploy is complete
|
|
38
|
+
console.log('DEPLOY COMPLETE')
|
|
39
|
+
})
|
|
40
|
+
// catch any errors and log them
|
|
41
|
+
.catch(error => {
|
|
42
|
+
console.log('Could not deploy theme')
|
|
43
|
+
console.log(error)
|
|
44
|
+
process.exit()
|
|
45
|
+
})
|
|
46
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const { spawn } = require('child_process')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
const dist = path.resolve(process.cwd(), ThemeEnvy.outputPath)
|
|
4
|
+
|
|
5
|
+
module.exports = async (newThemeID) => {
|
|
6
|
+
return new Promise((resolve, reject) => {
|
|
7
|
+
try {
|
|
8
|
+
// shopify push
|
|
9
|
+
const push = spawn('shopify', ['theme', 'push', '--theme=' + newThemeID, '--ignore=*.json', '--path=' + dist])
|
|
10
|
+
push.stdout.setEncoding('utf8')
|
|
11
|
+
push.stdout.on('data', data => {
|
|
12
|
+
console.log(data)
|
|
13
|
+
})
|
|
14
|
+
push.on('close', () => {
|
|
15
|
+
resolve(newThemeID)
|
|
16
|
+
})
|
|
17
|
+
const handleError = (error) => {
|
|
18
|
+
reject(error)
|
|
19
|
+
console.error(error.message)
|
|
20
|
+
throw new Error('Could not push theme')
|
|
21
|
+
}
|
|
22
|
+
push.stderr.on('data', handleError)
|
|
23
|
+
push.on('error', handleError)
|
|
24
|
+
return newThemeID
|
|
25
|
+
} catch (error) {
|
|
26
|
+
console.log(error)
|
|
27
|
+
reject(error)
|
|
28
|
+
// exit the process
|
|
29
|
+
process.exit()
|
|
30
|
+
}
|
|
31
|
+
})
|
|
32
|
+
}
|
package/index.js
CHANGED
|
@@ -19,6 +19,7 @@ const themeEnvyCommands = {
|
|
|
19
19
|
build: require('#Build'),
|
|
20
20
|
clean: require('#Helpers/functions/dist-clean.js'),
|
|
21
21
|
convert: require('#Convert'),
|
|
22
|
+
deploy: require('#Helpers/functions/deploy/index.js'),
|
|
22
23
|
dev: require('#Helpers/functions/dev.js'),
|
|
23
24
|
init: require('#Init'),
|
|
24
25
|
ignore: require('#Ignore'),
|
|
@@ -88,6 +89,14 @@ This does the following things:
|
|
|
88
89
|
themeEnvyCommands.init(source, options)
|
|
89
90
|
})
|
|
90
91
|
|
|
92
|
+
program
|
|
93
|
+
.command('deploy')
|
|
94
|
+
.description('Deploy your theme to Shopify by copying the live theme then pushing changes to codebase on top of it')
|
|
95
|
+
.action((options, command) => {
|
|
96
|
+
scriptMessage(command.name())
|
|
97
|
+
themeEnvyCommands.deploy()
|
|
98
|
+
})
|
|
99
|
+
|
|
91
100
|
program
|
|
92
101
|
.command('dev')
|
|
93
102
|
.description('Start development process and sync with Shopify using the Shopify CLI')
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
name: Deploy Production Theme
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
# trigger on v* tags
|
|
6
|
+
tags:
|
|
7
|
+
- 'v*'
|
|
8
|
+
# allow tests from pushes to branch
|
|
9
|
+
branches:
|
|
10
|
+
- 'deploy-release-action'
|
|
11
|
+
|
|
12
|
+
# or manually
|
|
13
|
+
workflow_dispatch:
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
deploy:
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
environment: production
|
|
19
|
+
|
|
20
|
+
# connects organization and repo variables and secrets to the runner
|
|
21
|
+
env:
|
|
22
|
+
SHOPIFY_FLAG_STORE: ${{ vars.SHOPIFY_FLAG_STORE }}
|
|
23
|
+
SHOPIFY_CLI_THEME_TOKEN: ${{ secrets.SHOPIFY_CLI_THEME_TOKEN }}
|
|
24
|
+
SHOPIFY_CLI_TTY: 0
|
|
25
|
+
steps:
|
|
26
|
+
# load the current repo on the runner
|
|
27
|
+
- name: checkout repo
|
|
28
|
+
uses: actions/checkout@v3
|
|
29
|
+
with:
|
|
30
|
+
token: ${{ secrets.WORKFLOW_REPO_ACCESS }}
|
|
31
|
+
|
|
32
|
+
# set up node
|
|
33
|
+
- name: use node
|
|
34
|
+
uses: actions/setup-node@v3
|
|
35
|
+
with:
|
|
36
|
+
node-version: '18.13.0'
|
|
37
|
+
|
|
38
|
+
# set up ruby
|
|
39
|
+
- name: use ruby
|
|
40
|
+
uses: ruby/setup-ruby@v1
|
|
41
|
+
with:
|
|
42
|
+
ruby-version: '3.0'
|
|
43
|
+
|
|
44
|
+
# install dependencies
|
|
45
|
+
- name: install dependencies
|
|
46
|
+
run: |
|
|
47
|
+
gem install bundler
|
|
48
|
+
npm install -g npm@8.19.2
|
|
49
|
+
npm install
|
|
50
|
+
|
|
51
|
+
# run deployment script from framework bin scripts
|
|
52
|
+
- name: deploy new theme
|
|
53
|
+
run: npx theme-envy deploy
|
|
@@ -25,4 +25,11 @@ module.exports = function({ target, opts }) {
|
|
|
25
25
|
if (err) return console.error(err)
|
|
26
26
|
console.log(`${logSymbols.success} Utils starter files copied`)
|
|
27
27
|
})
|
|
28
|
+
|
|
29
|
+
// copy github deploy workflow
|
|
30
|
+
const githubDeploySrc = path.resolve(__dirname, './.github/workflows/deploy.yml')
|
|
31
|
+
fs.copy(githubDeploySrc, path.resolve(target, '.github/workflows/deploy.yml'), err => {
|
|
32
|
+
if (err) return console.error(err)
|
|
33
|
+
console.log(`${logSymbols.success} GitHub deploy workflow copied`)
|
|
34
|
+
})
|
|
28
35
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description runs directly after a deployment to Shopify to run any additional processes or notifications a user may want to run
|
|
3
|
+
* @param {string} themeId - The theme ID that was just deployed
|
|
4
|
+
* @returns {Void}
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
module.exports = ({ themeName, themeID }) => {
|
|
8
|
+
// placeholder
|
|
9
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@softlimit/theme-envy",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11-alpha",
|
|
4
4
|
"description": "Softlimit Shopify Theme Development Environment",
|
|
5
5
|
"bin": {
|
|
6
6
|
"theme-envy": "./index.js"
|
|
@@ -84,6 +84,7 @@
|
|
|
84
84
|
},
|
|
85
85
|
"devDependencies": {
|
|
86
86
|
"caller": "^1.1.0",
|
|
87
|
+
"dotenv": "^16.4.5",
|
|
87
88
|
"jsdoc": "^4.0.2"
|
|
88
89
|
}
|
|
89
90
|
}
|