@wipcomputer/deploy-public 1.0.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.
- package/LICENSE +52 -0
- package/SKILL.md +71 -0
- package/deploy-public.sh +170 -0
- package/package.json +9 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
Dual License: MIT + AGPLv3
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 WIP Computer, Inc.
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
1. MIT License (local and personal use)
|
|
7
|
+
---------------------------------------
|
|
8
|
+
|
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
10
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
11
|
+
in the Software without restriction, including without limitation the rights
|
|
12
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
13
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
14
|
+
furnished to do so, subject to the following conditions:
|
|
15
|
+
|
|
16
|
+
The above copyright notice and this permission notice shall be included in all
|
|
17
|
+
copies or substantial portions of the Software.
|
|
18
|
+
|
|
19
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
20
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
21
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
22
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
23
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
24
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
25
|
+
SOFTWARE.
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
2. GNU Affero General Public License v3.0 (commercial and cloud use)
|
|
29
|
+
--------------------------------------------------------------------
|
|
30
|
+
|
|
31
|
+
If you run this software as part of a hosted service, cloud platform,
|
|
32
|
+
marketplace listing, or any network-accessible offering for commercial
|
|
33
|
+
purposes, the AGPLv3 terms apply. You must either:
|
|
34
|
+
|
|
35
|
+
a) Release your complete source code under AGPLv3, or
|
|
36
|
+
b) Obtain a commercial license.
|
|
37
|
+
|
|
38
|
+
This program is free software: you can redistribute it and/or modify
|
|
39
|
+
it under the terms of the GNU Affero General Public License as published
|
|
40
|
+
by the Free Software Foundation, either version 3 of the License, or
|
|
41
|
+
(at your option) any later version.
|
|
42
|
+
|
|
43
|
+
This program is distributed in the hope that it will be useful,
|
|
44
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
45
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
46
|
+
GNU Affero General Public License for more details.
|
|
47
|
+
|
|
48
|
+
You should have received a copy of the GNU Affero General Public License
|
|
49
|
+
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
AGPLv3 for personal use is free. Commercial licenses available.
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: deploy-public
|
|
3
|
+
description: Private-to-public repo sync. Copies everything except ai/ to the public mirror. Creates PR, merges, syncs releases.
|
|
4
|
+
license: MIT
|
|
5
|
+
interface: [cli, skill]
|
|
6
|
+
metadata:
|
|
7
|
+
display-name: "Private-to-Public Sync"
|
|
8
|
+
version: "1.3.0"
|
|
9
|
+
homepage: "https://github.com/wipcomputer/wip-ai-devops-toolbox"
|
|
10
|
+
author: "Parker Todd Brooks"
|
|
11
|
+
category: dev-tools
|
|
12
|
+
capabilities:
|
|
13
|
+
- repo-sync
|
|
14
|
+
- release-sync
|
|
15
|
+
requires:
|
|
16
|
+
bins: [git, gh, bash]
|
|
17
|
+
openclaw:
|
|
18
|
+
requires:
|
|
19
|
+
bins: [git, gh, bash]
|
|
20
|
+
emoji: "🚢"
|
|
21
|
+
compatibility: Requires git, gh (GitHub CLI), bash.
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
# deploy-public
|
|
25
|
+
|
|
26
|
+
Private-to-public repo sync. One script for all repos. Copies code, creates a PR on the public repo, merges it, and syncs GitHub releases.
|
|
27
|
+
|
|
28
|
+
## When to Use This Skill
|
|
29
|
+
|
|
30
|
+
**Use deploy-public for:**
|
|
31
|
+
- Publishing a private repo's code to its public counterpart
|
|
32
|
+
- After running `wip-release` on the private repo (release must exist first)
|
|
33
|
+
- Syncing release notes from private to public
|
|
34
|
+
|
|
35
|
+
**CRITICAL: Release order matters.**
|
|
36
|
+
1. Merge PR to private repo's main
|
|
37
|
+
2. Run `wip-release` (creates GitHub release with notes on private repo)
|
|
38
|
+
3. THEN run `deploy-public.sh` (pulls notes from private release)
|
|
39
|
+
|
|
40
|
+
If you skip step 2, the public release gets empty notes.
|
|
41
|
+
|
|
42
|
+
### Do NOT Use For
|
|
43
|
+
|
|
44
|
+
- Repos without a `-private` counterpart
|
|
45
|
+
- First-time repo setup (create the public repo on GitHub first)
|
|
46
|
+
|
|
47
|
+
## API Reference
|
|
48
|
+
|
|
49
|
+
### CLI
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
bash scripts/deploy-public.sh /path/to/private-repo org/public-repo
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Examples
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Deploy memory-crystal
|
|
59
|
+
bash scripts/deploy-public.sh /path/to/memory-crystal-private wipcomputer/memory-crystal
|
|
60
|
+
|
|
61
|
+
# Deploy wip-dev-tools
|
|
62
|
+
bash scripts/deploy-public.sh /path/to/wip-ai-devops-toolbox-private wipcomputer/wip-ai-devops-toolbox
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## What It Does
|
|
66
|
+
|
|
67
|
+
1. Clones the public repo to a temp directory
|
|
68
|
+
2. Copies all files from private repo (excluding `ai/`, `.git/`)
|
|
69
|
+
3. Creates a branch, commits, pushes, creates PR
|
|
70
|
+
4. Merges the PR (regular merge, never squash)
|
|
71
|
+
5. Syncs GitHub releases (pulls notes from private repo's releases)
|
package/deploy-public.sh
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# deploy-public.sh ... sync a private repo to its public counterpart
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# bash deploy-public.sh <private-repo-path> <public-github-repo>
|
|
7
|
+
#
|
|
8
|
+
# Example:
|
|
9
|
+
# bash deploy-public.sh /path/to/memory-crystal wipcomputer/memory-crystal
|
|
10
|
+
#
|
|
11
|
+
# Convention:
|
|
12
|
+
# - Private repo: {name}-private (where all work happens)
|
|
13
|
+
# - Public repo: {name} (deployment target, never work here directly)
|
|
14
|
+
# - ai/ folder is excluded from public deploys
|
|
15
|
+
# - Old ai/ in public git history is fine, just not going forward
|
|
16
|
+
#
|
|
17
|
+
# Location: wip-dev-guide-private/scripts/deploy-public.sh (one script for all repos)
|
|
18
|
+
|
|
19
|
+
set -euo pipefail
|
|
20
|
+
|
|
21
|
+
PRIVATE_REPO="$1"
|
|
22
|
+
PUBLIC_REPO="$2"
|
|
23
|
+
|
|
24
|
+
if [[ -z "$PRIVATE_REPO" || -z "$PUBLIC_REPO" ]]; then
|
|
25
|
+
echo "Usage: bash deploy-public.sh <private-repo-path> <public-github-repo>"
|
|
26
|
+
echo "Example: bash deploy-public.sh /path/to/memory-crystal wipcomputer/memory-crystal"
|
|
27
|
+
exit 1
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
if [[ ! -d "$PRIVATE_REPO/.git" ]]; then
|
|
31
|
+
echo "Error: $PRIVATE_REPO is not a git repository"
|
|
32
|
+
exit 1
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
# Get the latest commit message from private repo
|
|
36
|
+
COMMIT_MSG=$(cd "$PRIVATE_REPO" && git log -1 --pretty=format:"%s")
|
|
37
|
+
COMMIT_HASH=$(cd "$PRIVATE_REPO" && git log -1 --pretty=format:"%h")
|
|
38
|
+
|
|
39
|
+
TMPDIR=$(mktemp -d)
|
|
40
|
+
trap 'rm -rf "$TMPDIR"' EXIT
|
|
41
|
+
|
|
42
|
+
echo "Cloning public repo $PUBLIC_REPO..."
|
|
43
|
+
gh repo clone "$PUBLIC_REPO" "$TMPDIR/public" -- --depth 1 2>/dev/null || {
|
|
44
|
+
echo "Public repo is empty or doesn't exist. Initializing..."
|
|
45
|
+
mkdir -p "$TMPDIR/public"
|
|
46
|
+
cd "$TMPDIR/public"
|
|
47
|
+
git init
|
|
48
|
+
git remote add origin "git@github.com:${PUBLIC_REPO}.git"
|
|
49
|
+
cd - > /dev/null
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
echo "Syncing files from private repo (excluding ai/, .git/)..."
|
|
53
|
+
|
|
54
|
+
# Remove all tracked files in public (except .git) so deleted files get removed
|
|
55
|
+
find "$TMPDIR/public" -mindepth 1 -maxdepth 1 ! -name .git -exec rm -rf {} +
|
|
56
|
+
|
|
57
|
+
# rsync from private, excluding ai/ and .git/
|
|
58
|
+
rsync -a \
|
|
59
|
+
--exclude='ai/' \
|
|
60
|
+
--exclude='_trash/' \
|
|
61
|
+
--exclude='.git/' \
|
|
62
|
+
--exclude='.DS_Store' \
|
|
63
|
+
--exclude='.wrangler/' \
|
|
64
|
+
--exclude='.claude/' \
|
|
65
|
+
--exclude='CLAUDE.md' \
|
|
66
|
+
"$PRIVATE_REPO/" "$TMPDIR/public/"
|
|
67
|
+
|
|
68
|
+
cd "$TMPDIR/public"
|
|
69
|
+
|
|
70
|
+
# Check if there are changes
|
|
71
|
+
if git diff --quiet HEAD -- 2>/dev/null && git diff --cached --quiet HEAD -- 2>/dev/null && [[ -z "$(git ls-files --others --exclude-standard)" ]]; then
|
|
72
|
+
echo "No changes to deploy."
|
|
73
|
+
exit 0
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
# Harness ID for branch prefix. Set HARNESS_ID env var, or auto-detect from private repo path.
|
|
77
|
+
if [[ -z "${HARNESS_ID:-}" ]]; then
|
|
78
|
+
case "$PRIVATE_REPO" in
|
|
79
|
+
*"Claude Code - Mini"*) HARNESS_ID="cc-mini" ;;
|
|
80
|
+
*"Claude Code - MBA"*) HARNESS_ID="cc-air" ;;
|
|
81
|
+
*"Lēsa"*) HARNESS_ID="oc-lesa-mini" ;;
|
|
82
|
+
*) HARNESS_ID="deploy" ;;
|
|
83
|
+
esac
|
|
84
|
+
fi
|
|
85
|
+
BRANCH="$HARNESS_ID/deploy-$(date +%Y%m%d-%H%M%S)"
|
|
86
|
+
|
|
87
|
+
git checkout -b "$BRANCH"
|
|
88
|
+
git add -A
|
|
89
|
+
git commit -m "$COMMIT_MSG (from $COMMIT_HASH)"
|
|
90
|
+
|
|
91
|
+
echo "Pushing branch $BRANCH to $PUBLIC_REPO..."
|
|
92
|
+
git push -u origin "$BRANCH"
|
|
93
|
+
|
|
94
|
+
echo "Creating PR..."
|
|
95
|
+
PR_URL=$(gh pr create -R "$PUBLIC_REPO" \
|
|
96
|
+
--head "$BRANCH" \
|
|
97
|
+
--title "$COMMIT_MSG" \
|
|
98
|
+
--body "Synced from private repo (commit $COMMIT_HASH).")
|
|
99
|
+
|
|
100
|
+
echo "Merging PR..."
|
|
101
|
+
PR_NUMBER=$(echo "$PR_URL" | grep -o '[0-9]*$')
|
|
102
|
+
gh pr merge "$PR_NUMBER" -R "$PUBLIC_REPO" --merge
|
|
103
|
+
|
|
104
|
+
# Delete the deploy branch (merged, no longer needed)
|
|
105
|
+
echo "Cleaning up deploy branch..."
|
|
106
|
+
gh api -X DELETE "repos/$PUBLIC_REPO/git/refs/heads/$BRANCH" 2>/dev/null && echo " ✓ Deleted branch $BRANCH" || echo " ! Could not delete branch (non-fatal)"
|
|
107
|
+
|
|
108
|
+
# Clean up any other non-main branches on public repo
|
|
109
|
+
echo "Checking for stale branches on public repo..."
|
|
110
|
+
STALE_BRANCHES=$(gh api "repos/$PUBLIC_REPO/branches" --paginate --jq '.[].name' 2>/dev/null | grep -v '^main$' || true)
|
|
111
|
+
if [[ -n "$STALE_BRANCHES" ]]; then
|
|
112
|
+
STALE_COUNT=$(echo "$STALE_BRANCHES" | wc -l | tr -d ' ')
|
|
113
|
+
echo " Found $STALE_COUNT stale branch(es). Deleting..."
|
|
114
|
+
echo "$STALE_BRANCHES" | while read -r stale; do
|
|
115
|
+
gh api -X DELETE "repos/$PUBLIC_REPO/git/refs/heads/$stale" 2>/dev/null && echo " ✓ Deleted $stale" || echo " ! Could not delete $stale"
|
|
116
|
+
done
|
|
117
|
+
else
|
|
118
|
+
echo " ✓ No stale branches"
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
echo "Code synced via PR: $PR_URL"
|
|
122
|
+
|
|
123
|
+
# ── Sync release to public repo ──
|
|
124
|
+
# If the private repo has a version tag, create a matching release on the public repo.
|
|
125
|
+
# Pulls full release notes from the private repo and rewrites any private repo references.
|
|
126
|
+
|
|
127
|
+
# Try package.json first, fall back to latest git tag
|
|
128
|
+
VERSION=$(cd "$PRIVATE_REPO" && node -p "require('./package.json').version" 2>/dev/null || echo "")
|
|
129
|
+
if [[ -z "$VERSION" ]]; then
|
|
130
|
+
# No package.json. Use the latest version tag (v*) in the repo
|
|
131
|
+
TAG=$(cd "$PRIVATE_REPO" && git tag -l 'v*' --sort=-version:refname 2>/dev/null | head -1 || echo "")
|
|
132
|
+
if [[ -n "$TAG" ]]; then
|
|
133
|
+
VERSION="${TAG#v}"
|
|
134
|
+
fi
|
|
135
|
+
fi
|
|
136
|
+
if [[ -n "$VERSION" ]]; then
|
|
137
|
+
TAG="v$VERSION"
|
|
138
|
+
EXISTING=$(gh release view "$TAG" -R "$PUBLIC_REPO" --json tagName 2>/dev/null || echo "")
|
|
139
|
+
if [[ -z "$EXISTING" ]]; then
|
|
140
|
+
# Get the private repo's GitHub path (e.g., wipcomputer/memory-crystal-private)
|
|
141
|
+
PRIVATE_GH=$(cd "$PRIVATE_REPO" && git remote get-url origin | sed 's/.*github.com[:/]\(.*\)\.git/\1/')
|
|
142
|
+
|
|
143
|
+
# Pull full release notes from private repo
|
|
144
|
+
NOTES=$(gh release view "$TAG" -R "$PRIVATE_GH" --json body -q '.body' 2>/dev/null || echo "")
|
|
145
|
+
|
|
146
|
+
if [[ -z "$NOTES" || "$NOTES" == "null" ]]; then
|
|
147
|
+
NOTES="Release $TAG"
|
|
148
|
+
else
|
|
149
|
+
# Rewrite private repo references to public repo
|
|
150
|
+
NOTES=$(echo "$NOTES" | sed "s|$PRIVATE_GH|$PUBLIC_REPO|g")
|
|
151
|
+
fi
|
|
152
|
+
|
|
153
|
+
echo "Creating release $TAG on $PUBLIC_REPO..."
|
|
154
|
+
gh release create "$TAG" -R "$PUBLIC_REPO" --title "$TAG" --notes "$NOTES" 2>/dev/null && echo " ✓ Release $TAG created on $PUBLIC_REPO" || echo " ✗ Release creation failed (non-fatal)"
|
|
155
|
+
else
|
|
156
|
+
# Update existing release notes (in case they were incomplete)
|
|
157
|
+
PRIVATE_GH=$(cd "$PRIVATE_REPO" && git remote get-url origin | sed 's/.*github.com[:/]\(.*\)\.git/\1/')
|
|
158
|
+
NOTES=$(gh release view "$TAG" -R "$PRIVATE_GH" --json body -q '.body' 2>/dev/null || echo "")
|
|
159
|
+
if [[ -n "$NOTES" && "$NOTES" != "null" ]]; then
|
|
160
|
+
NOTES=$(echo "$NOTES" | sed "s|$PRIVATE_GH|$PUBLIC_REPO|g")
|
|
161
|
+
gh release edit "$TAG" -R "$PUBLIC_REPO" --notes "$NOTES" 2>/dev/null && echo " ✓ Release $TAG notes updated on $PUBLIC_REPO" || true
|
|
162
|
+
fi
|
|
163
|
+
echo " Release $TAG exists on $PUBLIC_REPO (notes synced)"
|
|
164
|
+
fi
|
|
165
|
+
fi
|
|
166
|
+
|
|
167
|
+
echo "Done. Public repo updated."
|
|
168
|
+
echo " PR: $PR_URL"
|
|
169
|
+
echo " Commit: $COMMIT_MSG (from $COMMIT_HASH)"
|
|
170
|
+
[[ -n "${VERSION:-}" ]] && echo " Release: v$VERSION"
|
package/package.json
ADDED