cpflow 5.0.4 → 5.1.0
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.
- checksums.yaml +4 -4
- data/.github/workflows/cpflow-promote-staging-to-production.yml +48 -9
- data/CHANGELOG.md +14 -1
- data/Gemfile.lock +1 -1
- data/README.md +32 -11
- data/docs/ai-github-flow-prompt.md +1 -1
- data/docs/ci-automation.md +94 -45
- data/docs/commands.md +9 -3
- data/docs/postgres.md +6 -0
- data/docs/rds-private-networking.md +649 -0
- data/docs/secrets-and-env-values.md +49 -0
- data/docs/tips.md +256 -10
- data/examples/controlplane.yml +8 -0
- data/lib/command/ai_github_flow_prompt.rb +1 -1
- data/lib/command/apply_template.rb +3 -0
- data/lib/command/base.rb +69 -0
- data/lib/command/cleanup_stale_apps.rb +1 -1
- data/lib/command/delete.rb +85 -10
- data/lib/command/deploy_image.rb +30 -8
- data/lib/command/generate_github_actions.rb +6 -0
- data/lib/command/setup_app.rb +11 -2
- data/lib/core/config.rb +81 -0
- data/lib/core/controlplane.rb +15 -5
- data/lib/core/template_parser.rb +4 -0
- data/lib/cpflow/version.rb +1 -1
- data/lib/generator_templates/controlplane.yml +7 -0
- data/lib/generator_templates_sqlite/controlplane.yml +7 -0
- data/lib/github_flow_templates/.github/cpflow-help.md +35 -12
- data/lib/github_flow_templates/.github/workflows/cpflow-promote-staging-to-production.yml +583 -15
- data/lib/github_flow_templates/bin/pin-cpflow-github-ref +17 -3
- data/lib/github_flow_templates/bin/test-cpflow-github-flow +61 -9
- metadata +3 -2
|
@@ -43,7 +43,10 @@ ruby <<'RUBY'
|
|
|
43
43
|
require "yaml"
|
|
44
44
|
|
|
45
45
|
CONTROL_PLANE_FLOW_WORKFLOW = %r{\Ashakacode/control-plane-flow/\.github/workflows/[^@\s]+@([^\s]+)\z}
|
|
46
|
-
PROMOTE_WORKFLOW = %r{\Ashakacode/control-plane-flow/\.github/workflows/cpflow-promote-staging-to-production\.yml@[^\s]
|
|
46
|
+
PROMOTE_WORKFLOW = %r{\Ashakacode/control-plane-flow/\.github/workflows/cpflow-promote-staging-to-production\.yml@([^\s]+)\z}
|
|
47
|
+
EXPECTED_PROMOTE_WORKFLOW_REF_FORMAT = "shakacode/control-plane-flow/.github/workflows/cpflow-promote-staging-to-production.yml@vX.Y.Z"
|
|
48
|
+
EXPECTED_CPFLOW_CHECKOUT_ACTION = "actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd"
|
|
49
|
+
EXPECTED_CPFLOW_CHECKOUT_REPOSITORY = "shakacode/control-plane-flow"
|
|
47
50
|
|
|
48
51
|
refs = Hash.new { |hash, key| hash[key] = [] }
|
|
49
52
|
|
|
@@ -72,19 +75,68 @@ Dir[".github/workflows/cpflow-*.yml"].sort.each do |path|
|
|
|
72
75
|
refs[uses_ref] << "#{path}:#{job_name}"
|
|
73
76
|
|
|
74
77
|
if job["uses"].to_s.match?(PROMOTE_WORKFLOW)
|
|
75
|
-
|
|
76
|
-
abort "#{path}:#{job_name} must set production_environment so GitHub can expose production environment secrets after approval"
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
secrets = job["secrets"].is_a?(Hash) ? job["secrets"] : {}
|
|
80
|
-
if secrets.key?("CPLN_TOKEN_PRODUCTION")
|
|
81
|
-
abort "#{path}:#{job_name} must not pass CPLN_TOKEN_PRODUCTION as a caller secret; store it on the protected production environment"
|
|
82
|
-
end
|
|
78
|
+
abort "#{path}:#{job_name} must not call the cross-repo production reusable workflow; use a normal caller-repo job with environment: production"
|
|
83
79
|
end
|
|
84
80
|
|
|
85
81
|
end
|
|
86
82
|
end
|
|
87
83
|
|
|
84
|
+
promote_path = ".github/workflows/cpflow-promote-staging-to-production.yml"
|
|
85
|
+
promote_doc = YAML.load_file(promote_path, aliases: true)
|
|
86
|
+
promote_job = promote_doc.fetch("jobs", {})["promote-to-production"]
|
|
87
|
+
|
|
88
|
+
unless promote_job
|
|
89
|
+
abort "#{promote_path}:promote-to-production job is missing"
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
if promote_job.key?("uses")
|
|
93
|
+
abort "#{promote_path}:promote-to-production must run as a normal caller-repo job, not a reusable workflow, so GitHub can expose production environment secrets"
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
unless promote_job["environment"].to_s == "production"
|
|
97
|
+
abort "#{promote_path}:promote-to-production must declare environment: production"
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
checkout_step = Array(promote_job["steps"]).find { |step| step["name"] == "Checkout control-plane-flow actions" }
|
|
101
|
+
|
|
102
|
+
unless checkout_step
|
|
103
|
+
abort "#{promote_path}:promote-to-production must include a Checkout control-plane-flow actions step"
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
unless checkout_step["uses"] == EXPECTED_CPFLOW_CHECKOUT_ACTION
|
|
107
|
+
abort "#{promote_path}:promote-to-production must use #{EXPECTED_CPFLOW_CHECKOUT_ACTION} for the Checkout control-plane-flow actions step"
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
checkout_with = checkout_step.fetch("with", {})
|
|
111
|
+
checkout_repository = checkout_with["repository"]
|
|
112
|
+
checkout_ref = checkout_with["ref"]
|
|
113
|
+
|
|
114
|
+
unless checkout_repository == EXPECTED_CPFLOW_CHECKOUT_REPOSITORY
|
|
115
|
+
abort "#{promote_path}:promote-to-production must check out #{EXPECTED_CPFLOW_CHECKOUT_REPOSITORY}"
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
if checkout_ref.to_s.strip.empty?
|
|
119
|
+
abort "#{promote_path}:promote-to-production must pin the Checkout control-plane-flow actions step"
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
refs[checkout_ref] << "#{promote_path}:promote-to-production"
|
|
123
|
+
|
|
124
|
+
setup_step = Array(promote_job["steps"]).find { |step| step["name"] == "Setup production environment" }
|
|
125
|
+
|
|
126
|
+
unless setup_step
|
|
127
|
+
abort "#{promote_path}:promote-to-production must include a Setup production environment step"
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
setup_ref = setup_step.fetch("with", {})["control_plane_flow_ref"]
|
|
131
|
+
setup_match = setup_ref.to_s.match(PROMOTE_WORKFLOW)
|
|
132
|
+
|
|
133
|
+
unless setup_match
|
|
134
|
+
abort "#{promote_path}:promote-to-production must pass a pinned production control_plane_flow_ref to setup, " \
|
|
135
|
+
"for example #{EXPECTED_PROMOTE_WORKFLOW_REF_FORMAT}"
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
refs[setup_match[1]] << "#{promote_path}:promote-to-production setup"
|
|
139
|
+
|
|
88
140
|
if refs.empty?
|
|
89
141
|
puts "no upstream cpflow reusable workflow refs found"
|
|
90
142
|
elsif refs.length > 1
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: cpflow
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.0
|
|
4
|
+
version: 5.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Justin Gordon
|
|
@@ -127,6 +127,7 @@ files:
|
|
|
127
127
|
- docs/dns.md
|
|
128
128
|
- docs/migrating-heroku-to-control-plane.md
|
|
129
129
|
- docs/postgres.md
|
|
130
|
+
- docs/rds-private-networking.md
|
|
130
131
|
- docs/redis.md
|
|
131
132
|
- docs/releasing.md
|
|
132
133
|
- docs/secrets-and-env-values.md
|
|
@@ -271,7 +272,7 @@ licenses:
|
|
|
271
272
|
metadata:
|
|
272
273
|
rubygems_mfa_required: 'true'
|
|
273
274
|
post_install_message: |
|
|
274
|
-
cpflow 5.0
|
|
275
|
+
cpflow 5.1.0 installed.
|
|
275
276
|
|
|
276
277
|
If this repository already uses generated cpflow GitHub Actions, update the
|
|
277
278
|
checked-in wrappers so GitHub loads the matching control-plane-flow release tag:
|