@styleflow.app/flowpress-deploy 1.0.0-beta.0 → 1.0.0-beta.10
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/CHANGELOG.md +70 -0
- package/README.md +6 -12
- package/composer.json +1 -1
- package/containers/cms/Dockerfile +35 -0
- package/containers/cms/Dockerfile.dockerignore +20 -0
- package/containers/cms/healthz.php +17 -0
- package/containers/cms/install-languages.sh +16 -0
- package/containers/cms/mpm.conf +10 -0
- package/containers/cms/php.ini +16 -0
- package/containers/cms/sanitize.php +37 -0
- package/containers/cms/smtp.php +13 -0
- package/containers/cms/vhost.conf +61 -0
- package/containers/cms/wp-cli.yml +1 -0
- package/containers/php-runtime/Dockerfile +21 -0
- package/containers/web-ssr/Dockerfile +25 -0
- package/containers/web-ssr/Dockerfile.dockerignore +10 -0
- package/containers/web-static/Caddyfile +40 -0
- package/containers/web-static/Dockerfile +15 -0
- package/containers/web-static/Dockerfile.dockerignore +7 -0
- package/dist/frontend-assets.d.ts +2 -0
- package/dist/frontend-assets.d.ts.map +1 -0
- package/dist/frontend-assets.js +44 -0
- package/dist/frontend-assets.js.map +1 -0
- package/dist/frontend-links.d.ts +14 -0
- package/dist/frontend-links.d.ts.map +1 -0
- package/dist/frontend-links.js +82 -0
- package/dist/frontend-links.js.map +1 -0
- package/dist/ops/bootstrap.d.ts +21 -0
- package/dist/ops/bootstrap.d.ts.map +1 -0
- package/dist/ops/bootstrap.js +123 -0
- package/dist/ops/bootstrap.js.map +1 -0
- package/dist/ops/build.d.ts +30 -0
- package/dist/ops/build.d.ts.map +1 -0
- package/dist/ops/build.js +99 -0
- package/dist/ops/build.js.map +1 -0
- package/dist/ops/cli.d.ts +3 -0
- package/dist/ops/cli.d.ts.map +1 -0
- package/dist/ops/cli.js +140 -0
- package/dist/ops/cli.js.map +1 -0
- package/dist/ops/config.d.ts +54 -0
- package/dist/ops/config.d.ts.map +1 -0
- package/dist/ops/config.js +163 -0
- package/dist/ops/config.js.map +1 -0
- package/dist/ops/coolify.d.ts +2 -0
- package/dist/ops/coolify.d.ts.map +1 -0
- package/dist/ops/coolify.js +44 -0
- package/dist/ops/coolify.js.map +1 -0
- package/dist/ops/data.d.ts +27 -0
- package/dist/ops/data.d.ts.map +1 -0
- package/dist/ops/data.js +148 -0
- package/dist/ops/data.js.map +1 -0
- package/dist/ops/deploy.d.ts +18 -0
- package/dist/ops/deploy.d.ts.map +1 -0
- package/dist/ops/deploy.js +100 -0
- package/dist/ops/deploy.js.map +1 -0
- package/dist/ops/editorial.d.ts +23 -0
- package/dist/ops/editorial.d.ts.map +1 -0
- package/dist/ops/editorial.js +79 -0
- package/dist/ops/editorial.js.map +1 -0
- package/dist/ops/environment.d.ts +29 -0
- package/dist/ops/environment.d.ts.map +1 -0
- package/dist/ops/environment.js +159 -0
- package/dist/ops/environment.js.map +1 -0
- package/dist/ops/health.d.ts +25 -0
- package/dist/ops/health.d.ts.map +1 -0
- package/dist/ops/health.js +22 -0
- package/dist/ops/health.js.map +1 -0
- package/dist/ops/monitor.d.ts +23 -0
- package/dist/ops/monitor.d.ts.map +1 -0
- package/dist/ops/monitor.js +142 -0
- package/dist/ops/monitor.js.map +1 -0
- package/dist/ops/process.d.ts +9 -0
- package/dist/ops/process.d.ts.map +1 -0
- package/dist/ops/process.js +48 -0
- package/dist/ops/process.js.map +1 -0
- package/dist/ops/provision.d.ts +41 -0
- package/dist/ops/provision.d.ts.map +1 -0
- package/dist/ops/provision.js +257 -0
- package/dist/ops/provision.js.map +1 -0
- package/dist/ops/release.d.ts +26 -0
- package/dist/ops/release.d.ts.map +1 -0
- package/dist/ops/release.js +79 -0
- package/dist/ops/release.js.map +1 -0
- package/dist/ops/s3.d.ts +8 -0
- package/dist/ops/s3.d.ts.map +1 -0
- package/dist/ops/s3.js +38 -0
- package/dist/ops/s3.js.map +1 -0
- package/dist/ops/static-config.d.ts +14 -0
- package/dist/ops/static-config.d.ts.map +1 -0
- package/dist/ops/static-config.js +96 -0
- package/dist/ops/static-config.js.map +1 -0
- package/dist/worker-assets.d.ts +5 -0
- package/dist/worker-assets.d.ts.map +1 -0
- package/dist/worker-assets.js +35 -0
- package/dist/worker-assets.js.map +1 -0
- package/docs/README.md +16 -0
- package/docs/activities/2026-07-30-2339-initial-pack.md +9 -0
- package/docs/activities/2026-08-24-1745-wordpress-core-v1.md +40 -0
- package/docs/activities/2026-08-26-0926-revision-safe-queue.md +41 -0
- package/docs/activities/README.md +5 -0
- package/docs/architecture.md +19 -0
- package/docs/configuration.md +19 -0
- package/docs/frontend-workflow.md +23 -0
- package/docs/operations.md +15 -0
- package/docs/recovery.md +16 -0
- package/docs/troubleshooting.md +22 -0
- package/docs/wordpress-queue.md +22 -0
- package/flowpress-deploy.php +33 -4
- package/includes/admin.php +110 -0
- package/includes/automatic-build.php +98 -0
- package/includes/manual-queue.php +78 -0
- package/includes/queue-provider.php +621 -0
- package/package.json +50 -7
- package/schema/deployment.schema.json +45 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
declare(strict_types=1);
|
|
4
|
+
defined('ABSPATH') || exit;
|
|
5
|
+
|
|
6
|
+
/** Debounce editorial changes; local fixtures never dispatch remote builds. */
|
|
7
|
+
function flowpress_deploy_schedule_public_build(int $delay = 60): void
|
|
8
|
+
{
|
|
9
|
+
if (! in_array(flowpress_env('APP_ENV'), ['staging', 'production'], true)
|
|
10
|
+
|| flowpress_env('CMS_GITHUB_DISPATCH_TOKEN') === ''
|
|
11
|
+
|| flowpress_env('GITHUB_REPOSITORY_SLUG') === ''
|
|
12
|
+
|| wp_next_scheduled('flowpress_deploy_dispatch_public_builds')) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
wp_schedule_single_event(time() + $delay, 'flowpress_deploy_dispatch_public_builds');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function flowpress_deploy_dispatch_public_builds(): void
|
|
19
|
+
{
|
|
20
|
+
if (! function_exists('flowpress_deploy_pending_count')) return;
|
|
21
|
+
global $wpdb;
|
|
22
|
+
foreach (flowpress_static_targets() as $target) {
|
|
23
|
+
if (flowpress_deploy_pending_count($target) === 0) continue;
|
|
24
|
+
$active = (int) $wpdb->get_var($wpdb->prepare(
|
|
25
|
+
'SELECT COUNT(*) FROM ' . flowpress_deploy_queue_table() . ' WHERE target = %s AND batch_id IS NOT NULL', $target
|
|
26
|
+
));
|
|
27
|
+
if ($active > 0) {
|
|
28
|
+
flowpress_deploy_schedule_public_build();
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
$result = flowpress_dispatch_build($target, true);
|
|
32
|
+
$failed = is_wp_error($result);
|
|
33
|
+
update_option('flowpress_deploy_build_dispatch_status', ['failed' => $failed, 'time' => time()], false);
|
|
34
|
+
if ($failed) {
|
|
35
|
+
error_log('FlowPress build dispatch failed: ' . $result->get_error_code());
|
|
36
|
+
flowpress_deploy_schedule_public_build(300);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
add_action('flowpress_deploy_dispatch_public_builds', 'flowpress_deploy_dispatch_public_builds');
|
|
41
|
+
|
|
42
|
+
add_action('save_post', static function (int $id, WP_Post $post): void {
|
|
43
|
+
if (! wp_is_post_revision($id) && ! wp_is_post_autosave($id)
|
|
44
|
+
&& in_array($post->post_type, array_merge(array_values(get_post_types(['public' => true])), ['wp_template', 'wp_template_part', 'wp_navigation', 'wp_block']), true)) {
|
|
45
|
+
flowpress_deploy_schedule_public_build();
|
|
46
|
+
}
|
|
47
|
+
}, 40, 2);
|
|
48
|
+
add_action('before_delete_post', static function (int $id, WP_Post $post): void {
|
|
49
|
+
if (in_array($post->post_type, array_merge(array_values(get_post_types(['public' => true])), ['wp_template', 'wp_template_part', 'wp_navigation', 'wp_block']), true)) flowpress_deploy_schedule_public_build();
|
|
50
|
+
}, 40, 2);
|
|
51
|
+
/** Public taxonomy edits can withdraw routes or change shared archive queries. */
|
|
52
|
+
function flowpress_deploy_taxonomy_affects_public_build(string $taxonomy): bool
|
|
53
|
+
{
|
|
54
|
+
$object = get_taxonomy($taxonomy);
|
|
55
|
+
return $object && (bool) apply_filters('flowpress_deploy_taxonomy_affects_public_build', $object->public, $taxonomy);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Term-only changes bypass save_post, including a public-to-private transition. */
|
|
59
|
+
add_action('set_object_terms', static function (int $id, $terms, $tt_ids, string $taxonomy, bool $append, $old_tt_ids): void {
|
|
60
|
+
$post = get_post($id);
|
|
61
|
+
if (! $post instanceof WP_Post || $post->post_status !== 'publish'
|
|
62
|
+
|| ! (get_post_type_object($post->post_type)->public ?? false)) return;
|
|
63
|
+
$current = array_map('intval', (array) $tt_ids);
|
|
64
|
+
$previous = array_map('intval', (array) $old_tt_ids);
|
|
65
|
+
sort($current); sort($previous);
|
|
66
|
+
if (! $append && $current === $previous) return;
|
|
67
|
+
// Hidden visibility/recipient taxonomies also affect public artifacts.
|
|
68
|
+
// A global descriptor avoids placing private titles or URLs in the queue.
|
|
69
|
+
flowpress_enqueue_build_change('global', 0, '/', 'update', true);
|
|
70
|
+
flowpress_deploy_schedule_public_build();
|
|
71
|
+
}, 40, 6);
|
|
72
|
+
foreach (['created_term', 'edited_term', 'pre_delete_term'] as $hook) {
|
|
73
|
+
$callback = $hook === 'pre_delete_term'
|
|
74
|
+
? static function (int $id, string $taxonomy): void {
|
|
75
|
+
if (flowpress_deploy_taxonomy_affects_public_build($taxonomy)) {
|
|
76
|
+
flowpress_enqueue_build_change('global', 0, '/', 'update', true);
|
|
77
|
+
flowpress_deploy_schedule_public_build();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
: static function (int $id, int $tt_id, string $taxonomy): void {
|
|
81
|
+
if (flowpress_deploy_taxonomy_affects_public_build($taxonomy)) {
|
|
82
|
+
flowpress_enqueue_build_change('global', 0, '/', 'update', true);
|
|
83
|
+
flowpress_deploy_schedule_public_build();
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
add_action($hook, $callback, 40, $hook === 'pre_delete_term' ? 2 : 3);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
add_action('admin_notices', static function (): void {
|
|
90
|
+
$status = get_option('flowpress_deploy_build_dispatch_status', []);
|
|
91
|
+
if (! empty($status['failed']) && current_user_can('edit_others_posts')) {
|
|
92
|
+
echo '<div class="notice notice-warning"><p>Avvio automatico della build non riuscito. Controlla la connessione GitHub in <a href="'
|
|
93
|
+
. esc_url(admin_url('tools.php?page=flowpress-builds')) . '">FlowPress Deploy</a>. Le modifiche pubbliche attendono il deploy riuscito.</p></div>';
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
add_action('flowpress_build_change_enqueued', 'flowpress_deploy_schedule_public_build');
|
|
98
|
+
add_action('save_post_wp_block', static function():void { flowpress_deploy_schedule_public_build(); });
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
if (! defined('ABSPATH')) {
|
|
4
|
+
exit;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function flowpress_deploy_manual_url(string $type, int $id): string
|
|
8
|
+
{
|
|
9
|
+
return wp_nonce_url(
|
|
10
|
+
admin_url('admin-post.php?action=flowpress_deploy_enqueue&type=' . rawurlencode($type) . '&id=' . $id),
|
|
11
|
+
'flowpress_deploy_enqueue_' . $type . '_' . $id
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function flowpress_deploy_post_action(array $actions, WP_Post $post): array
|
|
16
|
+
{
|
|
17
|
+
if (current_user_can('edit_post', $post->ID)) {
|
|
18
|
+
$actions['flowpress_deploy_enqueue'] = '<a href="' . esc_url(flowpress_deploy_manual_url('post', $post->ID)) . '">Aggiungi alla build queue</a>';
|
|
19
|
+
}
|
|
20
|
+
return $actions;
|
|
21
|
+
}
|
|
22
|
+
add_filter('post_row_actions', 'flowpress_deploy_post_action', 20, 2);
|
|
23
|
+
add_filter('page_row_actions', 'flowpress_deploy_post_action', 20, 2);
|
|
24
|
+
|
|
25
|
+
add_action('post_submitbox_misc_actions', static function (WP_Post $post): void {
|
|
26
|
+
if (! current_user_can('edit_post', $post->ID)) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
echo '<div class="misc-pub-section"><a class="button" href="'
|
|
30
|
+
. esc_url(flowpress_deploy_manual_url('post', $post->ID))
|
|
31
|
+
. '">Aggiungi alla build queue</a></div>';
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
add_filter('term_row_actions', static function (array $actions, WP_Term $term): array {
|
|
35
|
+
$taxonomy = get_taxonomy($term->taxonomy);
|
|
36
|
+
if ($taxonomy && current_user_can($taxonomy->cap->edit_terms)) {
|
|
37
|
+
$actions['flowpress_deploy_enqueue'] = '<a href="'
|
|
38
|
+
. esc_url(flowpress_deploy_manual_url('term-' . $term->taxonomy, $term->term_id))
|
|
39
|
+
. '">Aggiungi alla build queue</a>';
|
|
40
|
+
}
|
|
41
|
+
return $actions;
|
|
42
|
+
}, 20, 2);
|
|
43
|
+
|
|
44
|
+
add_action('admin_post_flowpress_deploy_enqueue', static function (): void {
|
|
45
|
+
$type = sanitize_key((string) ($_GET['type'] ?? ''));
|
|
46
|
+
$id = max(0, (int) ($_GET['id'] ?? 0));
|
|
47
|
+
check_admin_referer('flowpress_deploy_enqueue_' . $type . '_' . $id);
|
|
48
|
+
$uri = '';
|
|
49
|
+
$resource_type = '';
|
|
50
|
+
if ($type === 'post' && current_user_can('edit_post', $id)) {
|
|
51
|
+
$post = get_post($id);
|
|
52
|
+
if ($post instanceof WP_Post) {
|
|
53
|
+
$resource_type = $post->post_type;
|
|
54
|
+
$uri = (string) get_permalink($post);
|
|
55
|
+
}
|
|
56
|
+
} elseif (str_starts_with($type, 'term-')) {
|
|
57
|
+
$taxonomy = substr($type, 5);
|
|
58
|
+
$object = get_taxonomy($taxonomy);
|
|
59
|
+
if ($object && current_user_can($object->cap->edit_terms)) {
|
|
60
|
+
$term = get_term($id, $taxonomy);
|
|
61
|
+
$link = $term instanceof WP_Term ? get_term_link($term) : '';
|
|
62
|
+
if (! is_wp_error($link)) {
|
|
63
|
+
$resource_type = $taxonomy;
|
|
64
|
+
$uri = (string) $link;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if ($resource_type === '' || $uri === '') {
|
|
69
|
+
wp_die('Forbidden', 403);
|
|
70
|
+
}
|
|
71
|
+
flowpress_deploy_enqueue_change($resource_type, $id, $uri, 'update', false);
|
|
72
|
+
set_transient('flowpress_build_notice_' . get_current_user_id(), [
|
|
73
|
+
'type' => 'success',
|
|
74
|
+
'message' => 'Contenuto aggiunto alla build queue.',
|
|
75
|
+
], 60);
|
|
76
|
+
wp_safe_redirect(wp_get_referer() ?: admin_url('tools.php?page=flowpress-builds'));
|
|
77
|
+
exit;
|
|
78
|
+
});
|