@webship.co/workspace 0.0.0-stage → 1.0.0-alpha1
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/PLUGINS.md +249 -0
- package/README.md +379 -2
- package/WORKSPACES.md +69 -0
- package/actions/ai-items.js +293 -0
- package/actions/audio.js +48 -0
- package/actions/build-order.js +79 -0
- package/actions/checks.js +95 -0
- package/actions/claude-session.js +104 -0
- package/actions/commands-center.js +258 -0
- package/actions/composer.js +267 -0
- package/actions/ddev-addons.js +90 -0
- package/actions/ddev-mail.js +80 -0
- package/actions/ddev.js +237 -0
- package/actions/folders.js +165 -0
- package/actions/graphs.js +107 -0
- package/actions/images-svg.js +33 -0
- package/actions/images.js +145 -0
- package/actions/navigation.js +190 -0
- package/actions/node.js +222 -0
- package/actions/notes.js +55 -0
- package/actions/obsidian.js +59 -0
- package/actions/plugins.js +36 -0
- package/actions/project-make.js +28 -0
- package/actions/rag.js +202 -0
- package/actions/row-actions.js +262 -0
- package/actions/screens.js +270 -0
- package/actions/testing.js +121 -0
- package/actions/video-edit.js +54 -0
- package/ai-inventory.js +182 -0
- package/ai-items.js +202 -0
- package/assistant-cast.js +176 -0
- package/assistant-suggestions.js +91 -0
- package/assistant.js +484 -0
- package/audio-voice.js +528 -0
- package/auth-google.js +260 -0
- package/build-ai.js +52 -0
- package/build-order-page.js +191 -0
- package/build-order.js +313 -0
- package/builder-args.js +117 -0
- package/changelog.js +302 -0
- package/chat-threads.js +134 -0
- package/checks.js +105 -0
- package/claude-args.js +282 -0
- package/claude-sessions.js +129 -0
- package/command-author.js +117 -0
- package/command-block.js +20 -0
- package/commands/defaults.yml +159 -0
- package/commands-page.js +460 -0
- package/commands.js +568 -0
- package/cucumber.js +43 -0
- package/ddev-addons-page.js +124 -0
- package/ddev-addons.js +154 -0
- package/ddev-custom-commands.js +96 -0
- package/ddev-domains.js +84 -0
- package/ddev-import.js +93 -0
- package/ddev-mail-page.js +167 -0
- package/ddev-mail.js +110 -0
- package/ddev-options.js +145 -0
- package/ddev-snapshots.js +126 -0
- package/ddev.js +145 -0
- package/docs/DEVELOPER-GUIDE.md +224 -0
- package/docs/README.md +252 -0
- package/docs/REFERENCE.md +684 -0
- package/docs/USER-GUIDE.md +697 -0
- package/docs/screenshots/assistant/avatar-board.png +0 -0
- package/docs/screenshots/assistant/avatar-coffee.png +0 -0
- package/docs/screenshots/assistant/avatar-colours.png +0 -0
- package/docs/screenshots/assistant/avatar-icons.png +0 -0
- package/docs/screenshots/assistant/avatar-moves.png +0 -0
- package/docs/screenshots/assistant/avatar-pick-cookieman.png +0 -0
- package/docs/screenshots/assistant/avatar-settings-voices.png +0 -0
- package/docs/screenshots/assistant/avatar-status.png +0 -0
- package/docs/screenshots/create-card/create-card.png +0 -0
- package/docs/screenshots/create-card/start-ai.png +0 -0
- package/docs/screenshots/guide-clone-address.png +0 -0
- package/docs/screenshots/guide-clone-worktree-off.png +0 -0
- package/docs/screenshots/guide-clone-worktree-on.png +0 -0
- package/docs/screenshots/guide-ddev-menu.png +0 -0
- package/docs/screenshots/guide-domains.png +0 -0
- package/docs/screenshots/guide-home.png +0 -0
- package/docs/screenshots/guide-ide-menu.png +0 -0
- package/docs/screenshots/guide-remove-refusal.png +0 -0
- package/docs/screenshots/guide-rows-worktree.png +0 -0
- package/docs/screenshots/guide-screens.png +0 -0
- package/docs/screenshots/guide-settings.png +0 -0
- package/docs/screenshots/guide-workspace-page.png +0 -0
- package/docs/screenshots/home/card-settings.png +0 -0
- package/docs/screenshots/home/drag-reorder.png +0 -0
- package/docs/screenshots/home/edit-card.png +0 -0
- package/docs/screenshots/images/claude-code-image.png +0 -0
- package/docs/screenshots/images/edit-with-ai.png +0 -0
- package/docs/screenshots/images/gallery.png +0 -0
- package/docs/screenshots/images/generate-description.png +0 -0
- package/docs/screenshots/images/generate-plan.png +0 -0
- package/docs/screenshots/images/providers.png +0 -0
- package/docs/screenshots/images/svg-form.png +0 -0
- package/docs/screenshots/images/svg-result.png +0 -0
- package/docs/screenshots/images/upload.png +0 -0
- package/docs/screenshots/new-folder/2-form.png +0 -0
- package/docs/screenshots/new-folder/8-ddev-options.png +0 -0
- package/docs/screenshots/new-folder/files-folder.png +0 -0
- package/docs/screenshots/projects/ddev-custom-commands.png +0 -0
- package/docs/screenshots/projects/state-chip-stop.png +0 -0
- package/docs/screenshots/readme/dashboard-dark.png +0 -0
- package/docs/screenshots/readme/dashboard-light.png +0 -0
- package/docs/screenshots/readme/dev-dark.png +0 -0
- package/docs/screenshots/readme/dev-light.png +0 -0
- package/docs/screenshots/readme/docs-dark.png +0 -0
- package/docs/screenshots/readme/docs-light.png +0 -0
- package/docs/screenshots/readme/icons/ai.svg +4 -0
- package/docs/screenshots/readme/icons/code.svg +4 -0
- package/docs/screenshots/readme/icons/docs.svg +4 -0
- package/docs/screenshots/readme/icons/services.svg +4 -0
- package/docs/screenshots/readme/icons/sites.svg +4 -0
- package/docs/screenshots/readme/test-report-dark.png +0 -0
- package/docs/screenshots/readme/test-report-light.png +0 -0
- package/docs/screenshots/readme/test-scenarios.png +0 -0
- package/docs/screenshots/readme/test-steps.png +0 -0
- package/docs/screenshots/readme/videos-dark.png +0 -0
- package/docs/screenshots/readme/videos-light.png +0 -0
- package/docs/screenshots/screens-menu.png +0 -0
- package/docs/screenshots/screens-new.png +0 -0
- package/docs/screenshots/settings/auth-google-lists.png +0 -0
- package/docs/screenshots/settings/delete-1-row.png +0 -0
- package/docs/screenshots/settings/delete-2-confirm.png +0 -0
- package/docs/screenshots/settings/delete-3-type-name.png +0 -0
- package/docs/screenshots/settings/delete-4-type-yes.png +0 -0
- package/event-log.js +59 -0
- package/files-browser.js +247 -0
- package/folders.js +121 -0
- package/format.js +73 -0
- package/git-info.js +81 -0
- package/github-auth.js +62 -0
- package/graphs.js +104 -0
- package/html.js +10 -0
- package/icons.js +83 -0
- package/images-ai.js +447 -0
- package/images-create.js +226 -0
- package/images-page.js +417 -0
- package/images-records.js +39 -0
- package/images-render.js +36 -0
- package/images-svg-core.js +214 -0
- package/images-svg-sanitize.js +188 -0
- package/images-svg.js +241 -0
- package/images.js +270 -0
- package/jobs.js +430 -0
- package/linger.js +21 -0
- package/lists.js +292 -0
- package/media-info.js +136 -0
- package/navigation-page.js +264 -0
- package/navigation.js +394 -0
- package/notes.js +0 -0
- package/obsidian.js +405 -0
- package/package.json +47 -4
- package/palette-index.js +46 -0
- package/playwright.config.js +23 -0
- package/plugin-install.js +239 -0
- package/plugin-loader.js +448 -0
- package/plugin-manifest.js +83 -0
- package/plugin-settings.js +44 -0
- package/plugins/workspace-notes/index.js +59 -0
- package/plugins-page.js +103 -0
- package/project-make.js +241 -0
- package/project-name.js +210 -0
- package/public/assistant-avatar-moves.js +646 -0
- package/public/assistant-avatar-ui.js +1223 -0
- package/public/assistant-avatar.js +530 -0
- package/public/avatar/druplicon.vrm +0 -0
- package/public/css/base.css +260 -0
- package/public/css/components/ai-assistant.css +263 -0
- package/public/css/components/assistant-avatar.css +279 -0
- package/public/css/components/assistant-views.css +198 -0
- package/public/css/components/build-order.css +74 -0
- package/public/css/components/clone-as-a-git-worktree.css +30 -0
- package/public/css/components/command-palette.css +61 -0
- package/public/css/components/commands-center.css +139 -0
- package/public/css/components/confirm-dialog.css +40 -0
- package/public/css/components/create-card.css +8 -0
- package/public/css/components/ddev-menu.css +23 -0
- package/public/css/components/deep-chat.css +17 -0
- package/public/css/components/density.css +11 -0
- package/public/css/components/floating-assistant-workspace-pages.css +55 -0
- package/public/css/components/folders.css +5 -0
- package/public/css/components/full-height-left-assistant-sidebar-all-pages.css +39 -0
- package/public/css/components/full-height-right-actions-rail-pages-that-have-actions.css +267 -0
- package/public/css/components/grid-and-list.css +203 -0
- package/public/css/components/help-page.css +36 -0
- package/public/css/components/hero.css +16 -0
- package/public/css/components/images.css +70 -0
- package/public/css/components/layout-rhythm-and-spacing-polish.css +139 -0
- package/public/css/components/mic-on-any-field-that-wants-typing.css +416 -0
- package/public/css/components/modal-fit.css +113 -0
- package/public/css/components/page-width.css +23 -0
- package/public/css/components/plugins-page.css +9 -0
- package/public/css/components/project-cards.css +256 -0
- package/public/css/components/project-rows.css +390 -0
- package/public/css/components/reordering-the-workspace-cards.css +85 -0
- package/public/css/components/responsive-home-and-the-workspace-pages.css +457 -0
- package/public/css/components/running-commands-as-toasts.css +327 -0
- package/public/css/components/settings-editor-core-config-yml.css +828 -0
- package/public/css/components/short-results-as-a-toast-at-the-top.css +203 -0
- package/public/css/components/sound-player.css +84 -0
- package/public/css/components/suggest-agents-skills-commands.css +112 -0
- package/public/css/components/tab-modal.css +142 -0
- package/public/css/components/terminals.css +244 -0
- package/public/css/components/test-report-media-one-file-per-row-paged.css +144 -0
- package/public/css/components/top-toolbar-logo-breadcrumb.css +107 -0
- package/public/css/components/video-edit.css +6 -0
- package/public/css/components/web-ide-open-with.css +23 -0
- package/public/css/components/working-indicators.css +158 -0
- package/public/css/components/workspace-cards.css +79 -0
- package/public/favicon.ico +0 -0
- package/public/favicon.png +0 -0
- package/public/htmx.min.js +1 -0
- package/public/logo.png +0 -0
- package/public/media-player.js +215 -0
- package/public/mic.js +255 -0
- package/public/narration.js +110 -0
- package/public/palette.js +278 -0
- package/public/sortable.js +251 -0
- package/public/suggest.js +337 -0
- package/public/terminal.js +903 -0
- package/public/themes/default/theme.css +267 -0
- package/public/themes/ember/theme.css +180 -0
- package/public/themes/press/theme.css +290 -0
- package/public/themes/slate/theme.css +182 -0
- package/public/touch-icon.png +0 -0
- package/public/ui.js +2721 -0
- package/public/vendor/ace/LICENSE.txt +24 -0
- package/public/vendor/ace/ace.js +23 -0
- package/public/vendor/ace/ext-language_tools.js +8 -0
- package/public/vendor/ace/ext-searchbox.js +8 -0
- package/public/vendor/ace/mode-css.js +8 -0
- package/public/vendor/ace/mode-html.js +8 -0
- package/public/vendor/ace/mode-javascript.js +8 -0
- package/public/vendor/ace/mode-markdown.js +8 -0
- package/public/vendor/ace/mode-sh.js +8 -0
- package/public/vendor/ace/mode-yaml.js +8 -0
- package/public/vendor/ace/theme-textmate.js +8 -0
- package/public/vendor/ace/theme-tomorrow_night.js +8 -0
- package/public/vendor/ace/worker-yaml.js +1 -0
- package/public/vendor/deep-chat.LICENSE +21 -0
- package/public/vendor/deep-chat.bundle.js +1 -0
- package/public/vendor/fonts/dm-serif-text-LICENSE.txt +93 -0
- package/public/vendor/fonts/dm-serif-text-latin-400-italic.woff2 +0 -0
- package/public/vendor/fonts/dm-serif-text-latin-400-normal.woff2 +0 -0
- package/public/vendor/fonts/figtree-LICENSE.txt +93 -0
- package/public/vendor/fonts/figtree-latin-400-italic.woff2 +0 -0
- package/public/vendor/fonts/figtree-latin-400-normal.woff2 +0 -0
- package/public/vendor/fonts/figtree-latin-600-italic.woff2 +0 -0
- package/public/vendor/fonts/figtree-latin-600-normal.woff2 +0 -0
- package/public/vendor/fonts/jetbrains-mono-LICENSE.txt +93 -0
- package/public/vendor/fonts/jetbrains-mono-latin-400-normal.woff2 +0 -0
- package/public/vendor/fonts/ubuntu-mono-LICENSE.txt +98 -0
- package/public/vendor/fonts/ubuntu-mono-latin-wght-normal.woff2 +0 -0
- package/public/vendor/tabler-LICENSE.txt +21 -0
- package/public/vendor/tabler-sprite.svg +1 -0
- package/public/vendor/three/LICENSE +21 -0
- package/public/vendor/three/addons/loaders/GLTFLoader.js +4860 -0
- package/public/vendor/three/addons/utils/BufferGeometryUtils.js +1501 -0
- package/public/vendor/three/addons/utils/SkeletonUtils.js +496 -0
- package/public/vendor/three/three.core.min.js +6 -0
- package/public/vendor/three/three.module.min.js +6 -0
- package/public/vendor/three-vrm/LICENSE +22 -0
- package/public/vendor/three-vrm/three-vrm.module.min.js +983 -0
- package/public/vendor/uikit-icons.min.js +1 -0
- package/public/vendor/uikit.min.css +1 -0
- package/public/vendor/uikit.min.js +1 -0
- package/public/vendor/webship-icons/ui/bookmark-outlined.svg +1 -0
- package/public/vendor/webship-icons/ui/headset.svg +1 -0
- package/public/vendor/webship-icons/ui/menu.svg +1 -0
- package/public/vendor/webship-icons/ui/pause.svg +1 -0
- package/public/vendor/webship-icons/ui/play.svg +1 -0
- package/public/vendor/webship-icons/ui/share.svg +1 -0
- package/public/vendor/webship-icons/ui/sound-off.svg +1 -0
- package/public/vendor/webship-icons/ui/sound-on.svg +1 -0
- package/public/vendor/webship-icons/ui/stop.svg +1 -0
- package/public/vendor/xterm/addon-fit.js +2 -0
- package/public/vendor/xterm/addon-unicode11.js +2 -0
- package/public/vendor/xterm/addon-web-links.js +2 -0
- package/public/vendor/xterm/xterm.css +218 -0
- package/public/vendor/xterm/xterm.js +2 -0
- package/rag.js +169 -0
- package/reader.js +132 -0
- package/repo-blobs.js +66 -0
- package/report-pdf.js +337 -0
- package/row-layout.js +1440 -0
- package/screenrc +37 -0
- package/screens.js +1063 -0
- package/scripts/code-server-start.sh +190 -0
- package/scripts/images-claude-finish.js +107 -0
- package/scripts/screen-host.sh +114 -0
- package/scripts/screen-runner.js +362 -0
- package/scripts/screen-then.js +47 -0
- package/scripts/update.sh +350 -0
- package/server.js +8140 -0
- package/settings-file.js +423 -0
- package/speech.js +297 -0
- package/tab-modal.js +75 -0
- package/test-reports.js +260 -0
- package/themes.js +381 -0
- package/transcripts.js +168 -0
- package/urls.js +13 -0
- package/validate.js +18 -0
- package/version-check.js +94 -0
- package/video-edit.js +588 -0
- package/waiting.js +85 -0
- package/workspace-card-tools.js +41 -0
- package/workspace-delete.js +139 -0
- package/workspace-types.js +85 -0
- package/workspaces.js +557 -0
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
# Update the Webship Workspace dashboard app to a released tag.
|
|
4
|
+
#
|
|
5
|
+
# bash core/workspace-app/scripts/update.sh --check installed vs the latest tag
|
|
6
|
+
# bash core/workspace-app/scripts/update.sh update to the latest tag
|
|
7
|
+
# bash core/workspace-app/scripts/update.sh --tag 1.0.3 pin a tag (any tarball-servable ref)
|
|
8
|
+
# bash core/workspace-app/scripts/update.sh --dry-run itemize, change nothing
|
|
9
|
+
# bash core/workspace-app/scripts/update.sh --no-prompts leave prompts/ alone
|
|
10
|
+
# bash core/workspace-app/scripts/update.sh --prompts-only sync only the prompts
|
|
11
|
+
# bash core/workspace-app/scripts/update.sh --baseline 1.0.0 the version your prompts
|
|
12
|
+
# came from, when it cannot be told
|
|
13
|
+
# bash core/workspace-app/scripts/update.sh --force-prompts take the release's copy of
|
|
14
|
+
# every prompt, local edits included
|
|
15
|
+
#
|
|
16
|
+
# Deliberately SELF-CONTAINED: no workspace bootstrap, no argparse, no function
|
|
17
|
+
# library — the updater must never depend on the tooling it might be replacing.
|
|
18
|
+
# Plain bash + curl/gh + tar + rsync, and it locates the app from its own path.
|
|
19
|
+
#
|
|
20
|
+
# It updates core/workspace-app: runtime state survives (node_modules is kept
|
|
21
|
+
# unless package.json changed — then npm install runs in DDEV; actions.log,
|
|
22
|
+
# screenshots, test reports and the .app-version marker stay).
|
|
23
|
+
#
|
|
24
|
+
# It does NOT change your configuration. core/config and settings.yml are not
|
|
25
|
+
# its business at all, and inside the app the DDEV project's own identity is
|
|
26
|
+
# preserved across the update: its name, the hostnames derived from that name,
|
|
27
|
+
# any additional_fqdns and any router ports. A workspace called something else —
|
|
28
|
+
# a second checkout at ~/test1-workspace serving test1-workspace.ddev.site — must
|
|
29
|
+
# still be called that afterwards, or the update would point it at the first
|
|
30
|
+
# one's domains. Per-machine .ddev/config.*.yaml overrides are left alone too.
|
|
31
|
+
#
|
|
32
|
+
# It also brings the released PROMPT TEMPLATES into prompts/, because the New
|
|
33
|
+
# screen form and the Jira verbs offer them: a release that improves a prompt is
|
|
34
|
+
# useless if the prompt never reaches the machine. That folder is a staging area
|
|
35
|
+
# where prompts get worked on, so a prompt YOU have edited is never overwritten.
|
|
36
|
+
#
|
|
37
|
+
# "Edited" means edited, not "differs from the new release": every install and
|
|
38
|
+
# update records the checksum of each prompt as it shipped (.prompts-shipped),
|
|
39
|
+
# so a prompt still matching what came with the installed version is refreshed,
|
|
40
|
+
# and only one you actually changed is kept and reported. Before that file
|
|
41
|
+
# exists, the installed version's own prompts are fetched once to work it out —
|
|
42
|
+
# and if even that is not resolvable, differing prompts are kept, which is the
|
|
43
|
+
# safe way to be wrong. --force-prompts takes the release's copy regardless,
|
|
44
|
+
# --no-prompts skips the whole step.
|
|
45
|
+
#
|
|
46
|
+
# core/scripts, core/config, settings.yml and the other workspace folders belong
|
|
47
|
+
# to core/scripts/sync-tooling.sh, never to this script.
|
|
48
|
+
|
|
49
|
+
set -u
|
|
50
|
+
|
|
51
|
+
APP_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
52
|
+
VERSION_FILE="${APP_DIR}/.app-version"
|
|
53
|
+
SHIPPED_FILE="${APP_DIR}/.prompts-shipped"
|
|
54
|
+
REPO="webship/workspace"
|
|
55
|
+
TAG=""
|
|
56
|
+
CHECK="no"
|
|
57
|
+
DRY_RUN="no"
|
|
58
|
+
PROMPTS="yes"
|
|
59
|
+
PROMPTS_ONLY="no"
|
|
60
|
+
BASELINE=""
|
|
61
|
+
FORCE_PROMPTS="no"
|
|
62
|
+
ROOT="$(cd "${APP_DIR}/../.." && pwd)"
|
|
63
|
+
|
|
64
|
+
while [ $# -gt 0 ]; do
|
|
65
|
+
case "$1" in
|
|
66
|
+
-t|--tag) TAG="${2:-}"; shift 2 ;;
|
|
67
|
+
-r|--repo) REPO="${2:-}"; shift 2 ;;
|
|
68
|
+
-c|--check) CHECK="yes"; shift ;;
|
|
69
|
+
-n|--dry-run) DRY_RUN="yes"; shift ;;
|
|
70
|
+
--no-prompts) PROMPTS="no"; shift ;;
|
|
71
|
+
--prompts-only) PROMPTS_ONLY="yes"; shift ;;
|
|
72
|
+
--baseline) BASELINE="${2:-}"; shift 2 ;;
|
|
73
|
+
--force-prompts) FORCE_PROMPTS="yes"; shift ;;
|
|
74
|
+
-h|--help)
|
|
75
|
+
sed -n '3,12p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'
|
|
76
|
+
exit 0 ;;
|
|
77
|
+
*) echo "Unknown option: $1 (see --help)"; exit 1 ;;
|
|
78
|
+
esac
|
|
79
|
+
done
|
|
80
|
+
|
|
81
|
+
installed="(untracked)"
|
|
82
|
+
[ -f "${VERSION_FILE}" ] && installed="$(cat "${VERSION_FILE}")"
|
|
83
|
+
# What the prompts on disk came with. It is the installed version UNLESS this run
|
|
84
|
+
# is the second half of an update that already bumped it — hence --baseline, which
|
|
85
|
+
# the re-exec passes through with the value from before the bump.
|
|
86
|
+
[ -z "${BASELINE}" ] && BASELINE="${installed}"
|
|
87
|
+
|
|
88
|
+
have_gh="no"
|
|
89
|
+
command -v gh > /dev/null 2>&1 && gh auth status > /dev/null 2>&1 && have_gh="yes"
|
|
90
|
+
|
|
91
|
+
# The newest tag, by version order — resolved only when needed, so an explicit
|
|
92
|
+
# --tag works before the first release exists.
|
|
93
|
+
latest="(no tags yet)"
|
|
94
|
+
if [ -z "${TAG}" ] || [ "${CHECK}" = "yes" ]; then
|
|
95
|
+
if [ "${have_gh}" = "yes" ]; then
|
|
96
|
+
found=$(gh api "repos/${REPO}/tags" --jq '.[].name' 2>/dev/null | sort -V | tail -1)
|
|
97
|
+
else
|
|
98
|
+
found=$(curl -fsSL "https://api.github.com/repos/${REPO}/tags" 2>/dev/null \
|
|
99
|
+
| grep -o '"name": *"[^"]*"' | cut -d'"' -f4 | sort -V | tail -1)
|
|
100
|
+
fi
|
|
101
|
+
[ -n "${found}" ] && latest="${found}"
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
wanted="${TAG:-${found:-}}"
|
|
105
|
+
|
|
106
|
+
echo "Installed: ${installed}"
|
|
107
|
+
echo "Latest: ${latest}"
|
|
108
|
+
if [ "${CHECK}" = "yes" ]; then
|
|
109
|
+
if [ "${latest}" = "(no tags yet)" ]; then
|
|
110
|
+
echo "Releases have not started (or no access) — nothing to compare."
|
|
111
|
+
elif [ "${installed}" = "${latest}" ]; then
|
|
112
|
+
echo "Up to date."
|
|
113
|
+
else
|
|
114
|
+
echo "An update is available: bash ${BASH_SOURCE[0]} --tag ${latest}"
|
|
115
|
+
fi
|
|
116
|
+
exit 0
|
|
117
|
+
fi
|
|
118
|
+
if [ -z "${wanted}" ]; then
|
|
119
|
+
echo "No tags found on ${REPO} — nothing to update from (releases have not started, or no access)."
|
|
120
|
+
exit 1
|
|
121
|
+
fi
|
|
122
|
+
if [ "${installed}" = "${wanted}" ] && [ "${DRY_RUN}" = "no" ] && [ "${PROMPTS}" = "no" ]; then
|
|
123
|
+
echo "Already on ${wanted} — nothing to do."
|
|
124
|
+
exit 0
|
|
125
|
+
fi
|
|
126
|
+
# Being on the version is not the same as having its prompts — which is exactly
|
|
127
|
+
# what happens the first time a release adds a step to this script.
|
|
128
|
+
if [ "${installed}" = "${wanted}" ] && [ "${PROMPTS_ONLY}" = "no" ]; then
|
|
129
|
+
echo "The app is already on ${wanted} — checking the prompts."
|
|
130
|
+
PROMPTS_ONLY="yes"
|
|
131
|
+
fi
|
|
132
|
+
|
|
133
|
+
workdir=$(mktemp -d)
|
|
134
|
+
trap 'rm -rf "${workdir}"' EXIT
|
|
135
|
+
echo "Downloading ${REPO}@${wanted}…"
|
|
136
|
+
if [ "${have_gh}" = "yes" ]; then
|
|
137
|
+
gh api "repos/${REPO}/tarball/${wanted}" > "${workdir}/app.tar.gz" || exit 1
|
|
138
|
+
else
|
|
139
|
+
curl -fsSL "https://api.github.com/repos/${REPO}/tarball/${wanted}" -o "${workdir}/app.tar.gz" || exit 1
|
|
140
|
+
fi
|
|
141
|
+
tar -xzf "${workdir}/app.tar.gz" -C "${workdir}"
|
|
142
|
+
extracted=$(find "${workdir}" -maxdepth 1 -type d ! -path "${workdir}" | head -1)
|
|
143
|
+
if [ ! -d "${extracted}/core/workspace-app" ]; then
|
|
144
|
+
echo "The tag's tarball carries no core/workspace-app — refusing."
|
|
145
|
+
exit 1
|
|
146
|
+
fi
|
|
147
|
+
|
|
148
|
+
deps_changed="no"
|
|
149
|
+
cmp -s "${extracted}/core/workspace-app/package.json" "${APP_DIR}/package.json" || deps_changed="yes"
|
|
150
|
+
ddev_changed="no"
|
|
151
|
+
diff -rq "${extracted}/core/workspace-app/.ddev" "${APP_DIR}/.ddev" > /dev/null 2>&1 || ddev_changed="yes"
|
|
152
|
+
|
|
153
|
+
updater_changed="no"
|
|
154
|
+
cmp -s "${extracted}/core/workspace-app/scripts/update.sh" "${BASH_SOURCE[0]}" || updater_changed="yes"
|
|
155
|
+
|
|
156
|
+
rsync_flags="-a --itemize-changes"
|
|
157
|
+
[ "${DRY_RUN}" = "yes" ] && rsync_flags="${rsync_flags} --dry-run"
|
|
158
|
+
if [ "${PROMPTS_ONLY}" = "yes" ]; then
|
|
159
|
+
echo "Only the prompts this time — ${APP_DIR} is already on ${wanted}."
|
|
160
|
+
else
|
|
161
|
+
# The DDEV project's identity, read before the release's config lands on top.
|
|
162
|
+
ddev_config="${APP_DIR}/.ddev/config.yaml"
|
|
163
|
+
local_name="" ; local_fqdns="" ; local_http="" ; local_https=""
|
|
164
|
+
if [ -f "${ddev_config}" ]; then
|
|
165
|
+
local_name=$(grep -m1 '^name:' "${ddev_config}" | sed 's/^name: *//')
|
|
166
|
+
local_fqdns=$(grep -m1 '^additional_fqdns:' "${ddev_config}")
|
|
167
|
+
local_http=$(grep -m1 '^router_http_port:' "${ddev_config}")
|
|
168
|
+
local_https=$(grep -m1 '^router_https_port:' "${ddev_config}")
|
|
169
|
+
fi
|
|
170
|
+
|
|
171
|
+
echo "Updating ${APP_DIR} (runtime state survives)…"
|
|
172
|
+
rsync ${rsync_flags} --delete \
|
|
173
|
+
--filter='protect .ddev/config.*.yaml' \
|
|
174
|
+
--exclude=node_modules --exclude=actions.log --exclude=logs --exclude=.app-version \
|
|
175
|
+
--exclude=.prompts-shipped --exclude=.chats --exclude=.memory --exclude=.voice-cache \
|
|
176
|
+
--exclude=screenshots --exclude='tests/reports' --exclude='.playwright-mcp' \
|
|
177
|
+
"${extracted}/core/workspace-app/" "${APP_DIR}/"
|
|
178
|
+
|
|
179
|
+
# Put the project's identity back. The hostnames are patterns built from the
|
|
180
|
+
# name (*.dev.<name>), so they are renamed with it — otherwise this checkout
|
|
181
|
+
# would answer on another one's domains.
|
|
182
|
+
if [ "${DRY_RUN}" = "no" ] && [ -n "${local_name}" ] && [ -f "${ddev_config}" ]; then
|
|
183
|
+
shipped_name=$(grep -m1 '^name:' "${ddev_config}" | sed 's/^name: *//')
|
|
184
|
+
if [ "${shipped_name}" != "${local_name}" ]; then
|
|
185
|
+
sed -i "1,/^name:/ s/^name: .*/name: ${local_name}/" "${ddev_config}"
|
|
186
|
+
sed -i "s/^\(- \"\*\..*\)${shipped_name}\"$/\1${local_name}\"/" "${ddev_config}"
|
|
187
|
+
echo "Kept this workspace's DDEV project name: ${local_name}"
|
|
188
|
+
fi
|
|
189
|
+
[ -n "${local_fqdns}" ] && sed -i "s/^additional_fqdns:.*/${local_fqdns}/" "${ddev_config}"
|
|
190
|
+
[ -n "${local_http}" ] && sed -i "s/^router_http_port:.*/${local_http}/" "${ddev_config}"
|
|
191
|
+
[ -n "${local_https}" ] && sed -i "s/^router_https_port:.*/${local_https}/" "${ddev_config}"
|
|
192
|
+
fi
|
|
193
|
+
fi
|
|
194
|
+
|
|
195
|
+
# The release brought a newer updater and the one running is the old one, so the
|
|
196
|
+
# steps the new version adds would be skipped in the very release that adds
|
|
197
|
+
# them. Hand the rest of the job to the new script, once.
|
|
198
|
+
if [ "${PROMPTS_ONLY}" = "no" ] && [ "${DRY_RUN}" = "no" ] && [ "${updater_changed}" = "yes" ] \
|
|
199
|
+
&& [ -z "${WORKSPACE_UPDATE_REEXEC:-}" ] && [ -f "${APP_DIR}/scripts/update.sh" ] \
|
|
200
|
+
&& grep -q -- '--prompts-only' "${APP_DIR}/scripts/update.sh"; then
|
|
201
|
+
echo "${wanted}" > "${VERSION_FILE}"
|
|
202
|
+
echo "The updater changed in ${wanted} — finishing with the new one."
|
|
203
|
+
extra=""
|
|
204
|
+
[ "${FORCE_PROMPTS}" = "yes" ] && extra="--force-prompts"
|
|
205
|
+
WORKSPACE_UPDATE_REEXEC=1 exec bash "${APP_DIR}/scripts/update.sh" \
|
|
206
|
+
--repo "${REPO}" --tag "${wanted}" --prompts-only --baseline "${installed}" ${extra}
|
|
207
|
+
fi
|
|
208
|
+
|
|
209
|
+
# This machine's Docker access, put back.
|
|
210
|
+
#
|
|
211
|
+
# The release's .ddev/ lands on top of the local one, and TWO files in it are
|
|
212
|
+
# per-machine, written by core/scripts/docker-gid.sh rather than by hand:
|
|
213
|
+
# docker-compose.dood.yaml (group_add — the GID the running process is granted)
|
|
214
|
+
# and web-build/Dockerfile.workspace-app (the GID the group is created with).
|
|
215
|
+
# The shipped values are placeholders.
|
|
216
|
+
#
|
|
217
|
+
# Nothing here noticed. The project NAME, ports and fqdns were carefully restored
|
|
218
|
+
# and the GID was not, so every supported update left the dashboard with a docker
|
|
219
|
+
# GID that is not this host's — and the failure is silent until the next
|
|
220
|
+
# `ddev restart`, when the container loses access to docker.sock and the dashboard
|
|
221
|
+
# reports EVERY project as Stopped while they all run perfectly well. That is an
|
|
222
|
+
# hour of debugging a fault that is not one, once per machine, per update.
|
|
223
|
+
#
|
|
224
|
+
# sync-tooling.sh has always re-run docker-gid.sh after mirroring, for exactly this
|
|
225
|
+
# reason. The updater has to as well: it is the path a machine on releases uses,
|
|
226
|
+
# and it is the only one those machines have.
|
|
227
|
+
if [ "${DRY_RUN}" = "no" ]; then
|
|
228
|
+
if [ -f "${ROOT}/core/scripts/docker-gid.sh" ]; then
|
|
229
|
+
bash "${ROOT}/core/scripts/docker-gid.sh" > /dev/null 2>&1 \
|
|
230
|
+
&& echo "Docker GID re-applied for this host." \
|
|
231
|
+
|| echo "⚠️ Could not re-apply the docker GID: bash core/scripts/docker-gid.sh"
|
|
232
|
+
else
|
|
233
|
+
# A tree with the app but not the tooling. Say it plainly rather than leave a
|
|
234
|
+
# dashboard that will go blind on its next restart with no clue why.
|
|
235
|
+
echo "⚠️ core/scripts/docker-gid.sh is not here, so this release's placeholder"
|
|
236
|
+
echo " docker GID is in place. On the next 'ddev restart' the dashboard will"
|
|
237
|
+
echo " show every project as Stopped. Fix it with:"
|
|
238
|
+
echo " bash core/scripts/sync-tooling.sh --pull"
|
|
239
|
+
fi
|
|
240
|
+
fi
|
|
241
|
+
|
|
242
|
+
# The prompt templates the dashboard offers. New ones arrive, ones still as they
|
|
243
|
+
# shipped are refreshed, and anything YOU edited stays exactly as it is: this
|
|
244
|
+
# folder is where prompts are written, not only where they are installed.
|
|
245
|
+
if [ "${PROMPTS}" = "yes" ] && [ -d "${extracted}/prompts" ]; then
|
|
246
|
+
mkdir -p "${ROOT}/prompts"
|
|
247
|
+
|
|
248
|
+
# What the installed version shipped, so "edited" can mean edited rather than
|
|
249
|
+
# "differs from the new release" — without it, every improved prompt would be
|
|
250
|
+
# kept out forever on an install nobody has touched.
|
|
251
|
+
if [ ! -f "${SHIPPED_FILE}" ] && [ "${BASELINE}" != "(untracked)" ] && [ "${BASELINE}" != "${wanted}" ]; then
|
|
252
|
+
echo "Working out which prompts you have edited (fetching ${BASELINE})…"
|
|
253
|
+
if [ "${have_gh}" = "yes" ]; then
|
|
254
|
+
gh api "repos/${REPO}/tarball/${BASELINE}" > "${workdir}/installed.tar.gz" 2>/dev/null
|
|
255
|
+
else
|
|
256
|
+
curl -fsSL "https://api.github.com/repos/${REPO}/tarball/${BASELINE}" -o "${workdir}/installed.tar.gz" 2>/dev/null
|
|
257
|
+
fi
|
|
258
|
+
if [ -s "${workdir}/installed.tar.gz" ]; then
|
|
259
|
+
mkdir -p "${workdir}/installed" && tar -xzf "${workdir}/installed.tar.gz" -C "${workdir}/installed" 2>/dev/null
|
|
260
|
+
base=$(find "${workdir}/installed" -maxdepth 2 -type d -name prompts | head -1)
|
|
261
|
+
if [ -n "${base}" ]; then
|
|
262
|
+
: > "${workdir}/shipped"
|
|
263
|
+
for old_prompt in "${base}"/*.md ; do
|
|
264
|
+
[ -e "${old_prompt}" ] || continue
|
|
265
|
+
printf '%s %s\n' "$(sha256sum "${old_prompt}" | cut -d' ' -f1)" "$(basename "${old_prompt}")" >> "${workdir}/shipped"
|
|
266
|
+
done
|
|
267
|
+
[ "${DRY_RUN}" = "no" ] && cp "${workdir}/shipped" "${SHIPPED_FILE}"
|
|
268
|
+
SHIPPED_LIST="${workdir}/shipped"
|
|
269
|
+
fi
|
|
270
|
+
fi
|
|
271
|
+
fi
|
|
272
|
+
[ -z "${SHIPPED_LIST:-}" ] && [ -f "${SHIPPED_FILE}" ] && SHIPPED_LIST="${SHIPPED_FILE}"
|
|
273
|
+
|
|
274
|
+
# Did this prompt arrive with the installed version and stay untouched?
|
|
275
|
+
as_shipped() {
|
|
276
|
+
[ -n "${SHIPPED_LIST:-}" ] || return 1
|
|
277
|
+
local want ; want=$(grep -F " $1" "${SHIPPED_LIST}" 2>/dev/null | head -1 | cut -d' ' -f1)
|
|
278
|
+
[ -n "${want}" ] || return 1
|
|
279
|
+
[ "${want}" = "$(sha256sum "$2" | cut -d' ' -f1)" ]
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
added=0 ; updated=0 ; kept=0
|
|
283
|
+
for src in "${extracted}"/prompts/*.md ; do
|
|
284
|
+
[ -e "${src}" ] || continue
|
|
285
|
+
name="$(basename "${src}")"
|
|
286
|
+
dest="${ROOT}/prompts/${name}"
|
|
287
|
+
if [ ! -e "${dest}" ]; then
|
|
288
|
+
[ "${DRY_RUN}" = "no" ] && cp "${src}" "${dest}"
|
|
289
|
+
added=$((added + 1)) ; echo " new prompt: ${name}"
|
|
290
|
+
elif cmp -s "${src}" "${dest}" ; then
|
|
291
|
+
: # already the released one
|
|
292
|
+
elif [ "${FORCE_PROMPTS}" = "yes" ] || as_shipped "${name}" "${dest}" ; then
|
|
293
|
+
[ "${DRY_RUN}" = "no" ] && cp "${src}" "${dest}"
|
|
294
|
+
updated=$((updated + 1)) ; echo " updated: ${name}"
|
|
295
|
+
else
|
|
296
|
+
kept=$((kept + 1)) ; echo " yours, kept: ${name}"
|
|
297
|
+
fi
|
|
298
|
+
done
|
|
299
|
+
|
|
300
|
+
# Record what this version ships, so the next update knows the same thing
|
|
301
|
+
# without fetching anything.
|
|
302
|
+
if [ "${DRY_RUN}" = "no" ]; then
|
|
303
|
+
: > "${SHIPPED_FILE}"
|
|
304
|
+
for src in "${extracted}"/prompts/*.md ; do
|
|
305
|
+
[ -e "${src}" ] || continue
|
|
306
|
+
printf '%s %s\n' "$(sha256sum "${src}" | cut -d' ' -f1)" "$(basename "${src}")" >> "${SHIPPED_FILE}"
|
|
307
|
+
done
|
|
308
|
+
fi
|
|
309
|
+
|
|
310
|
+
echo "Prompts: ${added} new, ${updated} updated, ${kept} left as yours."
|
|
311
|
+
if [ "${kept}" -gt 0 ]; then
|
|
312
|
+
if [ -n "${SHIPPED_LIST:-}" ]; then
|
|
313
|
+
echo " (take the release's copy of those too with --force-prompts)"
|
|
314
|
+
else
|
|
315
|
+
echo " Nothing to compare them against, so they were all kept. If you have not edited them,"
|
|
316
|
+
echo " re-run with --baseline <the version they came from>, or --force-prompts."
|
|
317
|
+
fi
|
|
318
|
+
fi
|
|
319
|
+
fi
|
|
320
|
+
|
|
321
|
+
if [ "${DRY_RUN}" = "yes" ]; then
|
|
322
|
+
echo "(dry run — nothing was changed)"
|
|
323
|
+
exit 0
|
|
324
|
+
fi
|
|
325
|
+
echo "${wanted}" > "${VERSION_FILE}"
|
|
326
|
+
if [ "${PROMPTS_ONLY}" = "yes" ]; then
|
|
327
|
+
echo ""
|
|
328
|
+
echo "*---------------------------------------------------------------------*"
|
|
329
|
+
echo " The dashboard app is on ${wanted}, prompts included."
|
|
330
|
+
echo "*---------------------------------------------------------------------*"
|
|
331
|
+
exit 0
|
|
332
|
+
fi
|
|
333
|
+
|
|
334
|
+
if [ "${deps_changed}" = "yes" ]; then
|
|
335
|
+
echo "package.json changed — installing dependencies…"
|
|
336
|
+
(cd "${APP_DIR}" && ddev exec npm install --no-audit --no-fund) \
|
|
337
|
+
|| echo "npm install failed — run it in ${APP_DIR} yourself."
|
|
338
|
+
fi
|
|
339
|
+
if [ "${ddev_changed}" = "yes" ]; then
|
|
340
|
+
echo ""
|
|
341
|
+
echo "⚠️ .ddev/ changed in this release — a full restart is needed:"
|
|
342
|
+
echo " cd ${APP_DIR} && ddev restart"
|
|
343
|
+
else
|
|
344
|
+
echo "Restarting the app…"
|
|
345
|
+
(cd "${APP_DIR}" && ddev exec supervisorctl restart webextradaemons:workspace-app) > /dev/null 2>&1 || true
|
|
346
|
+
fi
|
|
347
|
+
echo ""
|
|
348
|
+
echo "*---------------------------------------------------------------------*"
|
|
349
|
+
echo " The dashboard app is on ${wanted}."
|
|
350
|
+
echo "*---------------------------------------------------------------------*"
|