wcc-contentful-app 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0a9ebca490bb9172d4e1b1a7449ed272b04e0f3f
4
+ data.tar.gz: 885ac69efd2ac212753c30c9e5022b295731f167
5
+ SHA512:
6
+ metadata.gz: 72f34bf7714650ce629162c6fc6dbbd45d2cc831cfdac4645f9fe72cc4a84480a6553a0f17931dffac8ab78ef46ce303c242580bc52b636e36ecf2cc01fbb93d
7
+ data.tar.gz: d03b0292853d51fcbc3b03253bf9534b4928caf1b5a52f65826092199fb24ae47a45d73476a0e24ee4df103586855b2ed7077655d26874b49e833742f58e3ef6
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --order rand
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
+
7
+ # Specify your gem's dependencies in wcc-contentful.gemspec
8
+ gemspec
9
+
10
+ gem 'wcc-contentful', path: File.expand_path('../wcc-contentful', __dir__)
File without changes
@@ -0,0 +1,24 @@
1
+ Description:
2
+ Generates the necessary migrations and initializers to add WCC Menus
3
+ to your contentful space.
4
+
5
+ Example:
6
+ rails generate wcc:model MODEL
7
+
8
+ This will install:
9
+ https://www.github.com/watermarkchurch/migration-cli
10
+
11
+ This will create:
12
+ db/migrate/[date]_generated_add_[MODEL].ts -
13
+ this migration is run by the migration CLI to create MODEL in your
14
+ contentful space
15
+ bin/release -
16
+ Adds a release command to your rails app which runs migrations.
17
+ bin/contentful -
18
+ This bash script is a wrapper around various Contentful CLI tools, and
19
+ is invoked by bin/release to run migrations
20
+ Procfile -
21
+ Adds a release command to be invoked by Heroku which runs the script
22
+ in bin/release
23
+ config/initializers/wcc_contentful.rb -
24
+ This file will initialize the wcc_contentful gem with default options
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Wcc
4
+ class ModelGenerator < Rails::Generators::Base
5
+ source_root File.expand_path('templates', __dir__)
6
+ argument :model, type: :string
7
+
8
+ VALID_MODELS = %w[menu page].freeze
9
+
10
+ def initialize(*)
11
+ super
12
+
13
+ return if VALID_MODELS.include?(singular)
14
+
15
+ raise ArgumentError, "Model must be #{VALID_MODELS.to_sentence}"
16
+ end
17
+
18
+ def ensure_migration_tools_installed
19
+ in_root do
20
+ run 'npm init -y' unless File.exist?('package.json')
21
+ package = JSON.parse(File.read('package.json'))
22
+ deps = package['dependencies']
23
+
24
+ unless deps.try(:[], 'contentful-migration-cli').present?
25
+ run 'npm install --save watermarkchurch/migration-cli ts-node typescript contentful-export'
26
+ end
27
+ end
28
+ end
29
+
30
+ def ensure_wrapper_script_in_bin_dir
31
+ unless inside('bin') { File.exist?('contentful') }
32
+ copy_file 'contentful_shell_wrapper', 'bin/contentful'
33
+ end
34
+
35
+ if inside('bin') { File.exist?('release') }
36
+ release = inside('bin') { File.read('release') }
37
+ unless release.include?('contentful migrate')
38
+ insert_into_file('bin/release', after: 'bundle exec rake db:migrate') do
39
+ <<~HEREDOC
40
+ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
41
+ $DIR/contentful migrate -y
42
+ HEREDOC
43
+ end
44
+ end
45
+ else
46
+ copy_file 'release', 'bin/release'
47
+ end
48
+
49
+ if in_root { File.exist?('Procfile') }
50
+ procfile = in_root { File.read('Procfile') }
51
+ unless procfile.include?('release:')
52
+ insert_into_file('Procfile') do
53
+ 'release: bin/release'
54
+ end
55
+ end
56
+ else
57
+ copy_file 'Procfile'
58
+ end
59
+ end
60
+
61
+ def ensure_initializer_exists
62
+ return if inside('config/initializers') { File.exist?('wcc_contentful.rb') }
63
+
64
+ copy_file 'wcc_contentful.rb', 'config/initializers/wcc_contentful.rb'
65
+ end
66
+
67
+ def create_model_migration
68
+ copy_file "#{singular}/generated_add_#{plural}.ts",
69
+ "db/migrate/#{timestamp}01_generated_add_#{plural}.ts"
70
+ end
71
+
72
+ def drop_model_overrides_in_app_models
73
+ directory "#{singular}/models", 'app/models'
74
+ end
75
+
76
+ private
77
+
78
+ def singular
79
+ model.downcase.singularize
80
+ end
81
+
82
+ def plural
83
+ model.downcase.pluralize
84
+ end
85
+
86
+ def timestamp
87
+ Time.now.strftime('%Y%m%d%H%M')
88
+ end
89
+ end
90
+ end
File without changes
@@ -0,0 +1,3 @@
1
+ web: bundle exec puma -C config/puma.rb
2
+ worker: bundle exec sidekiq
3
+ release: bin/release
@@ -0,0 +1,385 @@
1
+ #!/bin/bash
2
+
3
+ COLOR_NC='\033[0m' # No Color
4
+ COLOR_GRAY='\033[1;30m'
5
+ COLOR_RED='\033[0;31m'
6
+ COLOR_LCYAN='\033[1;36m'
7
+ COLOR_YELLOW='\033[1;33m'
8
+ COLOR_LGREEN='\033[1;32m'
9
+
10
+ logv() {
11
+ [[ -z "$VERBOSE" ]] && return 0;
12
+
13
+ local msg=$(echo "$@" | sed "s/$CONTENTFUL_MANAGEMENT_TOKEN/\*\*\*\*\*/" )
14
+ >&2 echo -e "${COLOR_GRAY}$msg${COLOR_NC}" || true
15
+ }
16
+
17
+ logerr() {
18
+ >&2 echo -e "${COLOR_RED}$@${COLOR_NC}"
19
+ }
20
+
21
+ curlv() {
22
+ logv "curl" $@
23
+ curl "$@"
24
+ }
25
+
26
+ execv() {
27
+ logv "$@"
28
+ "$@"
29
+ }
30
+
31
+ ## *** Argument Parsing & validation ***
32
+
33
+ usage() {
34
+ echo "$0 <command> [opts]
35
+ Commands:
36
+ migrate [dir|file]
37
+ runs pending migration files in the given directory
38
+ * [dir|file] optional - Default: db/migrate
39
+
40
+ setup [file]
41
+ initializes a space with bare-minimum schema and seeds
42
+ * [file] optional - default: db/contentful-schema.json
43
+
44
+ backup [file]
45
+ downloads a backup of the current space to the given file
46
+ * [file] optional - default: timestamped file in current directory
47
+
48
+ clean [no-init]
49
+ Deletes all data in a given space and optionally sets it up again
50
+ using 'bin/contentful setup'.
51
+ * [no-init] optional - Skips the 'setup' step at the end.
52
+
53
+ restore [file]
54
+ restores a given backup file into the current space
55
+ * [file] optional - default: the most recent backup file in the current directory
56
+
57
+ new_env
58
+ deletes the current working environment if it exists and makes a new clone of 'master'.
59
+ * -e [to environment ID] optional - the current working environment. Default: \$USER
60
+
61
+ generate [name]
62
+ Creates a sample migration in the db/migrate directory
63
+ * [name] optional - default: 'contentful_migration'
64
+
65
+ Flags:" && \
66
+ grep " .)\ #" $0
67
+ echo "
68
+ Examples:" && \
69
+ grep -i "#\ example:" $0 | awk '{$1=""; $2=""; print " "$0}'
70
+ }
71
+
72
+ parse_args() {
73
+ OPTIND=1
74
+ local s=$(echo "$1" | tr '[:upper:]' '[:lower:]')
75
+ case "$s" in
76
+ migrate|setup|backup|export|restore|new_env|import|generate|clean|help|h|\?)
77
+ export subcommand=$s
78
+ OPTIND=2
79
+ ;;
80
+ esac
81
+
82
+ # Parse flags
83
+ while getopts ":hyvse:a:" arg; do
84
+ case $arg in
85
+ y) # Yes - skip prompts
86
+ export YES="-y"
87
+ ;;
88
+ s) # Contentful Space ID - overrides env var CONTENTFUL_SPACE_ID
89
+ export CONTENTFUL_SPACE_ID=$OPTARG
90
+ ;;
91
+ a) # Contentful Mgmt Token - overrides env var CONTENTFUL_MANAGEMENT_TOKEN
92
+ export CONTENTFUL_MANAGEMENT_TOKEN=$OPTARG
93
+ ;;
94
+ e) # Contentful environment ID - overrides env var CONTENTFUL_ENVIRONMENT
95
+ export CONTENTFUL_ENVIRONMENT=$OPTARG
96
+ ;;
97
+ v) # Verbose mode - extra output
98
+ export VERBOSE=true
99
+ ;;
100
+ h) # Display help.
101
+ usage
102
+ exit 0
103
+ ;;
104
+ *)
105
+ logerr "Unknown option: '$OPTARG'"
106
+ usage
107
+ exit -1
108
+ ;;
109
+ esac
110
+ done
111
+
112
+ export OPTIND
113
+ }
114
+
115
+ parse_args $@ && shift $(($OPTIND - 1))
116
+ # If they put args before the command like 'bin/contentful -s 1xab migrate -y', try parsing again
117
+ [[ -z "$subcommand" ]] && parse_args $@ && shift $(($OPTIND - 1))
118
+
119
+ require_environment() {
120
+ [[ -z "$CONTENTFUL_SPACE_ID" ]] && logerr "Please set CONTENTFUL_SPACE_ID environment variable or use '-s' flag." && exit -1;
121
+ [[ -z "$CONTENTFUL_MANAGEMENT_TOKEN" ]] && logerr "Please set CONTENTFUL_MANAGEMENT_TOKEN environment variable or use '-a' flag." && exit -1;
122
+ if [[ ! -f node_modules/.bin/contentful-migration ]]; then
123
+ command -v npm >/dev/null 2>&1 || (logerr "I require 'npm' but it's not installed. Please install nodejs."; exit -1)
124
+ execv npm install
125
+ [[ -f node_modules/.bin/contentful-migration ]] || (logerr "Failed installing node modules - please ensure contentful CLI is installed"; exit -1)
126
+ fi
127
+ }
128
+
129
+ ## *** Utility functions ***
130
+
131
+ confirm() {
132
+ [[ -z "$2" ]] && [[ ! -z "$YES" ]] && logv "$1 (y/n): confirmed by -y flag" && return 0;
133
+
134
+ while true; do
135
+ if [[ -z "$2" ]]; then
136
+ read -p $'\033[1;36m'"$1"' (y/n): '$'\033[0m' yn
137
+ else
138
+ # double confirm - extra dangerous.
139
+ read -p $'\033[0;31m'"$1"' (y/n): '$'\033[0m' yn
140
+ fi
141
+ case $yn in
142
+ [Yy]* ) return 0;;
143
+ [Nn]* ) return 1;;
144
+ * ) echo "Please answer yes or no.";;
145
+ esac
146
+ done
147
+ }
148
+
149
+ get_space_name() {
150
+ curlv -s https://api.contentful.com/spaces/$1?access_token=$CONTENTFUL_MANAGEMENT_TOKEN | jq -r .name | tr '[:upper:]' '[:lower:]'
151
+ }
152
+
153
+ # Man I wish I understood sed... https://stackoverflow.com/a/29060802
154
+ # $1 File
155
+ # $2 Find
156
+ # $3 Replace / Append
157
+ replace_append() {
158
+ if grep -q "^$2" "$1"
159
+ then
160
+ sed -i.bak "s/^$2.*$/$3/" "$1"
161
+ else
162
+ echo "\n$3" >> "$1"
163
+ fi
164
+ }
165
+
166
+ set -e
167
+
168
+ # *** Commands ***
169
+
170
+ # Example: bin/contentful migrate -y -s 1xab -a $MY_TOKEN db/migrate/20180101120000_add_content_type_dog.ts
171
+ # equivalent to: bin/rake db:migrate
172
+ migrate() {
173
+ ARG="$1"
174
+ [[ -z "$ARG" ]] && ARG="db/migrate"
175
+ [[ -d "$ARG" ]] && ARG="batch $ARG"
176
+
177
+ require_environment
178
+
179
+ [[ ! -z "$CONTENTFUL_ENVIRONMENT" ]] && ENV="--environment-id $CONTENTFUL_ENVIRONMENT"
180
+
181
+ execv node_modules/.bin/ts-node node_modules/.bin/contentful-migration \
182
+ -s $CONTENTFUL_SPACE_ID $ENV -a $CONTENTFUL_MANAGEMENT_TOKEN \
183
+ $YES -p $ARG
184
+
185
+ mkdir -p db
186
+ execv node_modules/.bin/contentful-export --export-dir db --content-file contentful-schema.json \
187
+ --space-id $CONTENTFUL_SPACE_ID $ENV --management-token $CONTENTFUL_MANAGEMENT_TOKEN \
188
+ --query-entries 'content_type=migrationHistory' \
189
+ --query-assets 'sys.id=false'
190
+
191
+ if [[ $(git diff-index --name-only HEAD | grep 'db/contentful-schema.json') == "" ]]; then
192
+ echo -e "${COLOR_LGREEN}✓ Schema in contentful space is equivalent to stored schema${COLOR_NC}"
193
+ else
194
+ echo -e "${COLOR_YELLOW}⚠️ Schema changed after running migrations${COLOR_NC}"
195
+ fi
196
+ }
197
+
198
+ # Example: bin/contentful backup -s 1xab -a $MY_TOKEN 2018_01_01.1xab.dump.json
199
+ # equivalent to: bin/rake db:dump[2018_01_01.dump]
200
+ backup() {
201
+ FILE="$1"
202
+ [[ ! -z "$FILE" ]] && FILE="--content-file $FILE" && shift
203
+
204
+ require_environment
205
+
206
+ [[ ! -z "$CONTENTFUL_ENVIRONMENT" ]] && ENV="--environment-id $CONTENTFUL_ENVIRONMENT"
207
+
208
+ execv node_modules/.bin/contentful-export $FILE \
209
+ --space-id $CONTENTFUL_SPACE_ID $ENV --management-token $CONTENTFUL_MANAGEMENT_TOKEN \
210
+ $@
211
+ }
212
+
213
+ # Example: bin/contentful restore -y -s 1xab -a $MY_TOKEN 2018_01_01.1xab.dump.json
214
+ # equivalent to: bin/rake db:restore[2018_01_01.dump]
215
+ restore() {
216
+ FILE="$1"
217
+ if [[ -z "$FILE" ]]; then
218
+ FILE=$(ls contentful-export-$CONTENTFUL_SPACE_ID-* | sort -r | head -n 1)
219
+ [[ -z "$FILE" ]] && logerr "No file given on command line" && exit -1
220
+ fi
221
+
222
+ name=$(get_space_name $CONTENTFUL_SPACE_ID)
223
+ if [[ ! -z "$CONTENTFUL_ENVIRONMENT" ]]; then
224
+ ENV="--environment-id $CONTENTFUL_ENVIRONMENT"
225
+ name="$name/$CONTENTFUL_ENVIRONMENT"
226
+ fi
227
+ confirm "Import $FILE into $name?" || exit -1
228
+
229
+ require_environment
230
+
231
+ execv node_modules/.bin/contentful-import \
232
+ --space-id $CONTENTFUL_SPACE_ID $ENV --management-token $CONTENTFUL_MANAGEMENT_TOKEN \
233
+ --content-file $FILE
234
+ }
235
+
236
+ # Example: bin/contentful setup -y -s 1xab -a $MY_TOKEN db/my-schema.json
237
+ # equivalent to: bin/rake db:setup
238
+ setup() {
239
+ FILE="$1"
240
+ [[ -z "$FILE" ]] && FILE=db/contentful-schema.json
241
+
242
+ name=$(get_space_name $CONTENTFUL_SPACE_ID)
243
+ if [[ ! -z "$CONTENTFUL_ENVIRONMENT" ]]; then
244
+ ENV="--environment-id $CONTENTFUL_ENVIRONMENT"
245
+ name="$name/$CONTENTFUL_ENVIRONMENT"
246
+ fi
247
+
248
+ confirm "Initialize space $name from seed file $FILE?" || exit -1
249
+
250
+ require_environment
251
+
252
+ execv node_modules/.bin/contentful-import \
253
+ --space-id $CONTENTFUL_SPACE_ID $ENV --management-token $CONTENTFUL_MANAGEMENT_TOKEN \
254
+ --content-file $FILE
255
+
256
+ migrate
257
+ }
258
+
259
+ # Example: bin/contentful clean -s 1xab -a $MY_TOKEN
260
+ clean() {
261
+ command -v jq >/dev/null 2>&1 || (logerr "I require 'jq' but it's not installed. Please run 'brew install jq'"; exit -1)
262
+
263
+ require_environment
264
+
265
+ [[ -z "$CONTENTFUL_ENVIRONMENT" ]] && CONTENTFUL_ENVIRONMENT="$USER"
266
+ [[ "$CONTENTFUL_ENVIRONMENT" == "master" ]] && logerr "cannot delete the master environment" && exit -1
267
+
268
+ name=$(get_space_name $CONTENTFUL_SPACE_ID)
269
+ code=$(curlv -s -o /dev/null -w "%{http_code}" https://api.contentful.com/spaces/$CONTENTFUL_SPACE_ID/environments/$CONTENTFUL_ENVIRONMENT\?access_token\=$CONTENTFUL_MANAGEMENT_TOKEN)
270
+ [[ $code == "404" ]] && logerr "$CONTENTFUL_ENVIRONMENT does not exist in $name" && return 0;
271
+
272
+ confirm "This will delete the '$CONTENTFUL_ENVIRONMENT' environment from $name. Are you sure?" || exit -1
273
+
274
+ local bkup_file="contentful-export-$CONTENTFUL_SPACE_ID-${CONTENTFUL_ENVIRONMENT}-`date +"%Y-%m-%dT%H-%M-%S"`.json"
275
+ backup $bkup_file
276
+
277
+ curlv --fail -XDELETE https://api.contentful.com/spaces/$CONTENTFUL_SPACE_ID/environments/$CONTENTFUL_ENVIRONMENT\?access_token\=$CONTENTFUL_MANAGEMENT_TOKEN
278
+ }
279
+
280
+ # Example: bin/contentful new_env -e gordon_dev
281
+ new_env() {
282
+ command -v jq >/dev/null 2>&1 || (logerr "I require 'jq' but it's not installed. Please run 'brew install jq'"; exit -1)
283
+
284
+ require_environment
285
+ name=$(get_space_name $CONTENTFUL_SPACE_ID)
286
+ [[ -z "$CONTENTFUL_ENVIRONMENT" ]] && CONTENTFUL_ENVIRONMENT="$USER"
287
+ [[ "$CONTENTFUL_ENVIRONMENT" == "master" ]] && logerr "cannot delete the master environment" && exit -1
288
+
289
+ echo -e "${COLOR_LCYAN}This will delete '$CONTENTFUL_ENVIRONMENT' and recreate it from master.${COLOR_NC}"
290
+ confirm "Continue?" || exit -1
291
+ export YES='-y' # don't keep bugging the user
292
+
293
+ clean
294
+
295
+ # make the environment
296
+ resp=$(curlv -s --fail -XPUT https://api.contentful.com/spaces/$CONTENTFUL_SPACE_ID/environments/$CONTENTFUL_ENVIRONMENT \
297
+ -H "Authorization: Bearer ${CONTENTFUL_MANAGEMENT_TOKEN}" \
298
+ -H "Content-Type: application/vnd.contentful.management.v1+json" \
299
+ -d "{ \"name\": \"${CONTENTFUL_ENVIRONMENT}\" }")
300
+
301
+ while [ ! $(echo "$resp" | jq -r .sys.status.sys.id) == "ready" ]
302
+ do
303
+ logv "waiting for environment $CONTENTFUL_ENVIRONMENT to be ready..."
304
+ sleep 1
305
+ resp=$(curlv -s https://api.contentful.com/spaces/$CONTENTFUL_SPACE_ID/environments/$CONTENTFUL_ENVIRONMENT \
306
+ -H "Authorization: Bearer ${CONTENTFUL_MANAGEMENT_TOKEN}")
307
+ done
308
+
309
+ logv "get the API keys and update the one matching ours to point to the new environment"
310
+ keys=$(curlv -s --fail https://api.contentful.com/spaces/$CONTENTFUL_SPACE_ID/api_keys\?access_token\=$CONTENTFUL_MANAGEMENT_TOKEN)
311
+ my_key=$(echo "$keys" | jq -r ".items[] | select(.accessToken == \"$CONTENTFUL_ACCESS_TOKEN\")")
312
+ my_key_id=$(echo "$my_key" | jq -r ".sys.id")
313
+ my_key_version=$(echo "$my_key" | jq -r ".sys.version")
314
+ new_env_links=$(echo "$my_key" | jq ".environments + [{ \"sys\": { \"id\": \"$CONTENTFUL_ENVIRONMENT\", \"type\": \"Link\", \"linkType\": \"Environment\" } }] | { \"environments\": . }")
315
+
316
+ curlv -s -o /dev/null --fail -XPUT https://api.contentful.com/spaces/$CONTENTFUL_SPACE_ID/api_keys/$my_key_id \
317
+ -H "Authorization: Bearer ${CONTENTFUL_MANAGEMENT_TOKEN}" \
318
+ -H "Content-Type: application/vnd.contentful.management.v1+json" \
319
+ -H "X-Contentful-Version: ${my_key_version}" \
320
+ -d "${new_env_links}"
321
+
322
+ execv replace_append .env.local "CONTENTFUL_ENVIRONMENT\=" "CONTENTFUL_ENVIRONMENT=$CONTENTFUL_ENVIRONMENT"
323
+ execv replace_append .env.test.local "CONTENTFUL_ENVIRONMENT\=" "CONTENTFUL_ENVIRONMENT=$CONTENTFUL_ENVIRONMENT"
324
+
325
+ echo "Environment ${CONTENTFUL_ENVIRONMENT} successfully created!"
326
+ }
327
+
328
+ # Example: bin/contentful generate add content type dog
329
+ # equivalent to: bin/rails generate migration add_content_type_dog
330
+ generate() {
331
+ migration="
332
+ import Migration from 'contentful-migration-cli'
333
+
334
+ export = function (migration: Migration) {
335
+ const dog = migration.createContentType('dog', {
336
+ name: 'Dog'
337
+ })
338
+
339
+ const name = dog.createField('name')
340
+ name.name('Name')
341
+ .type('Symbol')
342
+ .required(true)
343
+ }
344
+ "
345
+
346
+ timestamp=$(date +%Y%m%d%H%M%S)
347
+ filename="$@"
348
+ [[ -z "$filename" ]] && filename="contentful_migration"
349
+ filename=${filename// /\_}
350
+ filename="db/migrate/${timestamp}_${filename}.ts"
351
+ echo "$migration" > $filename
352
+ echo "generated file $filename"
353
+ }
354
+
355
+ case $subcommand in
356
+ migrate)
357
+ migrate $@
358
+ ;;
359
+ backup|export)
360
+ backup $@
361
+ ;;
362
+ restore|import)
363
+ restore $@
364
+ ;;
365
+ setup)
366
+ setup $@
367
+ ;;
368
+ generate)
369
+ generate $@
370
+ ;;
371
+ clean)
372
+ clean $@
373
+ ;;
374
+ new_env)
375
+ new_env $@
376
+ ;;
377
+ help|h|\?)
378
+ usage
379
+ ;;
380
+ *)
381
+ logerr "Unknown command: '$1'"
382
+ usage
383
+ exit -1
384
+ ;;
385
+ esac