Skip to content

Commit

Permalink
Merge pull request #304 from Shopify/readonly_flag
Browse files Browse the repository at this point in the history
Readonly flag
  • Loading branch information
tanema authored Jan 4, 2017
2 parents d7ffb48 + 40bd866 commit bea25b7
Show file tree
Hide file tree
Showing 12 changed files with 130 additions and 27 deletions.
1 change: 1 addition & 0 deletions cmd/download_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ func (suite *DownloadTestSuite) TestDownloadWithFileNames() {
err := download(client, []string{"assets/hello.txt"})
assert.Nil(suite.T(), err)

client.Config.ReadOnly = true
err = download(client, []string{"output/nope.txt"})
assert.NotNil(suite.T(), err)
}
Expand Down
6 changes: 6 additions & 0 deletions cmd/remove.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ For more documentation please see http://shopify.github.io/themekit/commands/#re

func remove(client kit.ThemeClient, filenames []string, wg *sync.WaitGroup) {
defer wg.Done()

if client.Config.ReadOnly {
kit.LogErrorf("[%s]environment is reaonly", kit.GreenText(client.Config.Environment))
return
}

for _, filename := range filenames {
wg.Add(1)
go performRemove(client, kit.Asset{Key: filename}, wg)
Expand Down
16 changes: 16 additions & 0 deletions cmd/remove_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,22 @@ func (suite *RemoveTestSuite) TestRemove() {
wg.Wait()
}

func (suite *RemoveTestSuite) TestReadOnlyRemove() {
requested := false
client, server := newClientAndTestServer(func(w http.ResponseWriter, r *http.Request) {
requested = true
})
defer server.Close()

var wg sync.WaitGroup
wg.Add(1)
client.Config.ReadOnly = true
go remove(client, []string{"templates/layout.liquid"}, &wg)
wg.Wait()

assert.Equal(suite.T(), false, requested)
}

func TestRemoveTestSuite(t *testing.T) {
suite.Run(t, new(RemoveTestSuite))
}
Expand Down
6 changes: 6 additions & 0 deletions cmd/replace.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ For more documentation please see http://shopify.github.io/themekit/commands/#re

func replace(client kit.ThemeClient, filenames []string, wg *sync.WaitGroup) {
defer wg.Done()

if client.Config.ReadOnly {
kit.LogErrorf("[%s]environment is reaonly", kit.GreenText(client.Config.Environment))
return
}

assetsActions := map[string]assetAction{}

if len(filenames) == 0 {
Expand Down
16 changes: 16 additions & 0 deletions cmd/replace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,22 @@ func (suite *ReplaceTestSuite) TestReplaceAll() {
}
}

func (suite *ReplaceTestSuite) TestReadOnlyReplace() {
requested := false
client, server := newClientAndTestServer(func(w http.ResponseWriter, r *http.Request) {
requested = true
})
defer server.Close()

var wg sync.WaitGroup
wg.Add(1)
client.Config.ReadOnly = true
go replace(client, []string{}, &wg)
wg.Wait()

assert.Equal(suite.T(), false, requested)
}

func TestReplaceTestSuite(t *testing.T) {
suite.Run(t, new(ReplaceTestSuite))
}
10 changes: 10 additions & 0 deletions cmd/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ For more documentation please see http://shopify.github.io/themekit/commands/#up

func upload(client kit.ThemeClient, filenames []string, wg *sync.WaitGroup) {
defer wg.Done()

if client.Config.ReadOnly {
kit.LogErrorf("[%s]environment is reaonly", kit.GreenText(client.Config.Environment))
return
}

var err error
localAssets := []kit.Asset{}

Expand Down Expand Up @@ -69,6 +75,10 @@ func performUpload(client kit.ThemeClient, asset kit.Asset, wg *sync.WaitGroup)
}

func uploadSettingsData(client kit.ThemeClient, filenames []string, wg *sync.WaitGroup) {
if client.Config.ReadOnly {
return
}

doupload := func() {
asset, err := client.LocalAsset(settingsDataKey)
if err != nil {
Expand Down
16 changes: 16 additions & 0 deletions cmd/upload_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,22 @@ func (suite *UploadTestSuite) TestUploadAll() {
}
}

func (suite *UploadTestSuite) TestReadOnlyUpload() {
requested := false
client, server := newClientAndTestServer(func(w http.ResponseWriter, r *http.Request) {
requested = true
})
defer server.Close()

var wg sync.WaitGroup
wg.Add(1)
client.Config.ReadOnly = true
go upload(client, []string{}, &wg)
wg.Wait()

assert.Equal(suite.T(), false, requested)
}

func (suite *UploadTestSuite) TestUploadSettingsData() {
requests := make(chan int, 100)
client, server := newClientAndTestServer(func(w http.ResponseWriter, r *http.Request) {
Expand Down
19 changes: 14 additions & 5 deletions cmd/watch.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,20 @@ For more documentation please see http://shopify.github.io/themekit/commands/#wa
func watch(themeClients []kit.ThemeClient) error {
watchers := []*kit.FileWatcher{}
defer func() {
kit.Print("Cleaning up watchers")
for _, watcher := range watchers {
watcher.StopWatching()
if len(watchers) > 0 {
kit.Print("Cleaning up watchers")
for _, watcher := range watchers {
watcher.StopWatching()
}
}
}()

for _, client := range themeClients {
if client.Config.ReadOnly {
kit.LogErrorf("[%s]environment is reaonly", kit.GreenText(client.Config.Environment))
continue
}

kit.Printf("[%s] Watching for file changes on host %s ", kit.GreenText(client.Config.Environment), kit.YellowText(client.Config.Domain))
watcher, err := client.NewFileWatcher(notifyFile, handleWatchEvent)
if err != nil {
Expand All @@ -47,8 +54,10 @@ func watch(themeClients []kit.ThemeClient) error {
watchers = append(watchers, watcher)
}

signal.Notify(signalChan, os.Interrupt)
<-signalChan
if len(watchers) > 0 {
signal.Notify(signalChan, os.Interrupt)
<-signalChan
}

return nil
}
Expand Down
11 changes: 11 additions & 0 deletions cmd/watch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,17 @@ func (suite *WatchTestSuite) TestWatch() {
watch([]kit.ThemeClient{client})
}

func (suite *WatchTestSuite) TestReadOnlyWatch() {
requested := false
client, server := newClientAndTestServer(func(w http.ResponseWriter, r *http.Request) {
requested = true
})
defer server.Close()
client.Config.ReadOnly = true
watch([]kit.ThemeClient{client})
assert.Equal(suite.T(), false, requested)
}

func (suite *WatchTestSuite) TestHandleWatchEvent() {
requests := make(chan int, 1000)
client, server := newClientAndTestServer(func(w http.ResponseWriter, r *http.Request) {
Expand Down
44 changes: 23 additions & 21 deletions docs/configuration/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ There are general values that you will be able to config for all of Theme Kit ac

| Attribute | Description
|:-------------|:---------------------
| password | Your API password
| theme_id | The theme that you want the command to take effect on. If you want to make changes to the current live theme you may set this value to `'live'`
| store | Your store's Shopify domain with the `.myshopify.com` postfix.
| directory | The project root directory. This allows you to run the command from another directory.
| password | Your API password
| theme_id | The theme that you want the command to take effect on. If you want to make changes to the current live theme you may set this value to `'live'`
| store | Your store's Shopify domain with the `.myshopify.com` postfix.
| directory | The project root directory. This allows you to run the command from another directory.
| ignore_files | A list of patterns to ignore when executing commands. Please see the [Ignore Patterns]({{ '/ignores' | prepend: site.baseurl }}) documentation.
| ignores | A list of file paths to files that contain ignore patterns. Please see the [Ignore Patterns]({{ '/ignores' | prepend: site.baseurl }}) documentation.
| proxy | A full URL to proxy your requests through.
| timeout | Request timeout. If you have larger files in your project that may take longer than the default 30s to upload, you may want to increase this value. You can set this value to 60s for seconds or 1m for one minute.
| ignores | A list of file paths to files that contain ignore patterns. Please see the [Ignore Patterns]({{ '/ignores' | prepend: site.baseurl }}) documentation.
| proxy | A full URL to proxy your requests through.
| timeout | Request timeout. If you have larger files in your project that may take longer than the default 30s to upload, you may want to increase this value. You can set this value to 60s for seconds or 1m for one minute.
| readonly | All actions are readonly. This means you can download from this environment but you cannot do any modifications to the theme on shopify.

## Config File

Expand All @@ -41,6 +42,7 @@ production:
theme_id: "456"
store: can-i-buy-a-feeling.myshopify.com
timeout: 60s
readonly: true
test:
password: 16ef663594568325d64408ebcdeef528
theme_id: "789"
Expand All @@ -57,14 +59,14 @@ All of the Theme Kit environment variables are prefixed with `THEMEKIT_`

| Attribute | Environment Variable |
|:-------------|:---------------------|:------------------|
| password | THEMEKIT_PASSWORD | |
| theme_id | THEMEKIT_THEME_ID | |
| store | THEMEKIT_STORE | |
| directory | THEMEKIT_DIRECTORY | |
| password | THEMEKIT_PASSWORD | |
| theme_id | THEMEKIT_THEME_ID | |
| store | THEMEKIT_STORE | |
| directory | THEMEKIT_DIRECTORY | |
| ignore_files | THEMEKIT_IGNORE_FILES| Use a ':' as a pattern separator. |
| ignores | THEMEKIT_IGNORES | Use a ':' as a file path separator. |
| proxy | THEMEKIT_PROXY | |
| timeout | THEMEKIT_TIMEOUT | |
| ignores | THEMEKIT_IGNORES | Use a ':' as a file path separator. |
| proxy | THEMEKIT_PROXY | |
| timeout | THEMEKIT_TIMEOUT | |

**Note** Any environment variable will take precedence over your `config.yml` values
so please keep that in mind while debugging your config.
Expand All @@ -76,14 +78,14 @@ debugging settings or scripting calls to Theme Kit from something like `cron`.

| Attribute | Flag | Shortcut
|:-------------|:----------------|:--------|
| password | `--password` | |
| theme_id | `--themeid` | |
| store | `--store` | -s |
| directory | `--directory` | -d |
| password | `--password` | |
| theme_id | `--themeid` | |
| store | `--store` | -s |
| directory | `--directory` | -d |
| ignore_files | `--ignored-file`| |
| ignores | `--ignores` | |
| proxy | `--proxy` | |
| timeout | `--timeout` | |
| ignores | `--ignores` | |
| proxy | `--proxy` | |
| timeout | `--timeout` | |

**Note** Any flag will take precedence over your `config.yml` and environment values
so please keep that in mind while debugging your config.
6 changes: 5 additions & 1 deletion kit/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type Configuration struct {
Proxy string `yaml:"proxy,omitempty" json:"proxy,omitempty" env:"THEMEKIT_PROXY"`
Ignores []string `yaml:"ignores,omitempty" json:"ignores,omitempty" env:"THEMEKIT_IGNORES" envSeparator:":"`
Timeout time.Duration `yaml:"timeout,omitempty" json:"timeout,omitempty" env:"THEMEKIT_TIMEOUT"`
ReadOnly bool `yaml:"readonly,omitempty" json:"readonly,omitempty" env:"-"`
}

// DefaultTimeout is the default timeout to kill any stalled processes.
Expand Down Expand Up @@ -129,6 +130,7 @@ IgnoredFiles %v
Proxy %v
Ignores %v
Timeout %v
ReadOnly %v
`,
conf.Password,
conf.ThemeID,
Expand All @@ -137,7 +139,9 @@ Timeout %v
conf.IgnoredFiles,
conf.Proxy,
conf.Ignores,
conf.Timeout)
conf.Timeout,
conf.ReadOnly,
)
}

func (conf Configuration) asYAML() *Configuration {
Expand Down
6 changes: 6 additions & 0 deletions kit/http_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,17 @@ func (client *httpClient) sendJSON(rtype requestType, event EventType, urlStr st
}

func (client *httpClient) sendRequest(rtype requestType, event EventType, urlStr string, body io.Reader) (*ShopifyResponse, Error) {
if client.config.ReadOnly && event != Retrieve {
return newShopifyResponse(rtype, event, urlStr, nil, fmt.Errorf("Theme is read only"))
}

req, err := client.newRequest(event, urlStr, body)
if err != nil {
return newShopifyResponse(rtype, event, urlStr, nil, err)
}

apiLimit.Wait()

resp, respErr := client.client.Do(req)
return newShopifyResponse(rtype, event, urlStr, resp, respErr)
}

0 comments on commit bea25b7

Please sign in to comment.