Add Galaxy build and deployment workflows
This commit is contained in:
@@ -7,6 +7,10 @@ This file provides guidance when working with code in this repository.
|
|||||||
### Build and Run
|
### Build and Run
|
||||||
- `cargo run` - Build and run Warp locally
|
- `cargo run` - Build and run Warp locally
|
||||||
- `cargo bundle --bin warp` - Bundle the main app
|
- `cargo bundle --bin warp` - Bundle the main app
|
||||||
|
- `make run` - Build and run `galaxy-oss`
|
||||||
|
- `make clean` - Remove Cargo build artifacts
|
||||||
|
- `make deploy` - Validate, update, clean, bundle, and upload Galaxy to Hermes
|
||||||
|
- `make install` - Validate, update, clean, bundle, and install Galaxy to `/Applications`
|
||||||
|
|
||||||
### Running with local warp-server
|
### Running with local warp-server
|
||||||
To connect Warp client to a local warp-server instance:
|
To connect Warp client to a local warp-server instance:
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
.PHONY: run clean deploy install
|
||||||
|
|
||||||
|
run:
|
||||||
|
cargo run --bin galaxy-oss
|
||||||
|
|
||||||
|
clean:
|
||||||
|
cargo clean
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
./script/build-and-upload-hermes.sh
|
||||||
|
|
||||||
|
install:
|
||||||
|
./script/build-and-install-to-applications.sh
|
||||||
@@ -267,7 +267,10 @@ function StepLine({ step }: { step: Step }) {
|
|||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const [steps, setSteps] = useState<Step[]>([
|
const [steps, setSteps] = useState<Step[]>([
|
||||||
{ label: "Build Galaxy", status: "pending" },
|
{ label: "Check working directory", status: "pending" },
|
||||||
|
{ label: "Pull current branch", status: "pending" },
|
||||||
|
{ label: "Clean Cargo build artifacts", status: "pending" },
|
||||||
|
{ label: "Bundle Galaxy", status: "pending" },
|
||||||
{ label: "Create Galaxy.zip", status: "pending" },
|
{ label: "Create Galaxy.zip", status: "pending" },
|
||||||
{ label: "Authenticate with Hermes", status: "pending" },
|
{ label: "Authenticate with Hermes", status: "pending" },
|
||||||
{ label: "Start multipart upload", status: "pending" },
|
{ label: "Start multipart upload", status: "pending" },
|
||||||
@@ -293,17 +296,45 @@ function App() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
// ─── Step 0: Build ──────────────────────────────────────────────
|
// ─── Step 0: Check working directory ───────────────────────────
|
||||||
updateStep(0, { status: "running" });
|
updateStep(0, { status: "running" });
|
||||||
await runCommandStreaming(
|
await runCommandStreaming(
|
||||||
"cargo bundle --bin galaxy-oss --package galaxy",
|
`if [ -n "$(git status --porcelain)" ]; then git status --short; exit 1; fi`,
|
||||||
WORKSPACE_ROOT,
|
WORKSPACE_ROOT,
|
||||||
(line) => appendLog(0, line)
|
(line) => appendLog(0, line)
|
||||||
);
|
);
|
||||||
updateStep(0, { status: "done" });
|
updateStep(0, { status: "done" });
|
||||||
|
|
||||||
// ─── Step 1: Zip ────────────────────────────────────────────────
|
// ─── Step 1: Pull current branch ────────────────────────────────
|
||||||
updateStep(1, { status: "running" });
|
updateStep(1, { status: "running" });
|
||||||
|
const branch = execSync("git branch --show-current", {
|
||||||
|
cwd: WORKSPACE_ROOT,
|
||||||
|
encoding: "utf8",
|
||||||
|
}).trim();
|
||||||
|
if (!branch) throw new Error("Cannot deploy from a detached HEAD");
|
||||||
|
await runCommandStreaming(
|
||||||
|
`git pull --ff-only origin "${branch}"`,
|
||||||
|
WORKSPACE_ROOT,
|
||||||
|
(line) => appendLog(1, line)
|
||||||
|
);
|
||||||
|
updateStep(1, { status: "done", detail: branch });
|
||||||
|
|
||||||
|
// ─── Step 2: Clean ──────────────────────────────────────────────
|
||||||
|
updateStep(2, { status: "running" });
|
||||||
|
await runCommandStreaming("cargo clean", WORKSPACE_ROOT, (line) => appendLog(2, line));
|
||||||
|
updateStep(2, { status: "done" });
|
||||||
|
|
||||||
|
// ─── Step 3: Bundle ─────────────────────────────────────────────
|
||||||
|
updateStep(3, { status: "running" });
|
||||||
|
await runCommandStreaming(
|
||||||
|
"cargo bundle --bin galaxy-oss --package galaxy",
|
||||||
|
WORKSPACE_ROOT,
|
||||||
|
(line) => appendLog(3, line)
|
||||||
|
);
|
||||||
|
updateStep(3, { status: "done" });
|
||||||
|
|
||||||
|
// ─── Step 4: Zip ────────────────────────────────────────────────
|
||||||
|
updateStep(4, { status: "running" });
|
||||||
|
|
||||||
// Find the .app bundle — cargo bundle outputs to target/debug/bundle/osx/
|
// Find the .app bundle — cargo bundle outputs to target/debug/bundle/osx/
|
||||||
const appDir = path.join(
|
const appDir = path.join(
|
||||||
@@ -314,19 +345,19 @@ function App() {
|
|||||||
|
|
||||||
// Remove old zip if exists
|
// Remove old zip if exists
|
||||||
execSync(`rm -f "${zipPath}"`, { stdio: "pipe" });
|
execSync(`rm -f "${zipPath}"`, { stdio: "pipe" });
|
||||||
// Zip the .app folder
|
// Preserve executable permissions, symlinks, and macOS bundle metadata.
|
||||||
await runCommandStreaming(
|
await runCommandStreaming(
|
||||||
`cd "${appDir}" && zip -r -y "${zipPath}" Galaxy.app`,
|
`ditto -c -k --keepParent "${path.join(appDir, "Galaxy.app")}" "${zipPath}"`,
|
||||||
WORKSPACE_ROOT,
|
WORKSPACE_ROOT,
|
||||||
(line) => appendLog(1, line)
|
(line) => appendLog(4, line)
|
||||||
);
|
);
|
||||||
|
|
||||||
const fileSize = statSync(zipPath).size;
|
const fileSize = statSync(zipPath).size;
|
||||||
const fileSizeMB = (fileSize / (1024 * 1024)).toFixed(1);
|
const fileSizeMB = (fileSize / (1024 * 1024)).toFixed(1);
|
||||||
updateStep(1, { status: "done", detail: `${fileSizeMB} MB` });
|
updateStep(4, { status: "done", detail: `${fileSizeMB} MB` });
|
||||||
|
|
||||||
// ─── Step 2: Authenticate ───────────────────────────────────────
|
// ─── Step 5: Authenticate ───────────────────────────────────────
|
||||||
updateStep(2, { status: "running" });
|
updateStep(5, { status: "running" });
|
||||||
|
|
||||||
const loginRes = await apiPost<{ token: string }>(
|
const loginRes = await apiPost<{ token: string }>(
|
||||||
`${BASE_URL}/api/auth/login`,
|
`${BASE_URL}/api/auth/login`,
|
||||||
@@ -334,11 +365,11 @@ function App() {
|
|||||||
COMMON_HEADERS
|
COMMON_HEADERS
|
||||||
);
|
);
|
||||||
const token = loginRes.token;
|
const token = loginRes.token;
|
||||||
appendLog(2, `Authenticated as ${HERMES_USER}`);
|
appendLog(5, `Authenticated as ${HERMES_USER}`);
|
||||||
updateStep(2, { status: "done" });
|
updateStep(5, { status: "done" });
|
||||||
|
|
||||||
// ─── Step 3: Start upload ───────────────────────────────────────
|
// ─── Step 6: Start upload ───────────────────────────────────────
|
||||||
updateStep(3, { status: "running" });
|
updateStep(6, { status: "running" });
|
||||||
|
|
||||||
const fileHash = computeFileHash(zipPath);
|
const fileHash = computeFileHash(zipPath);
|
||||||
|
|
||||||
@@ -354,14 +385,14 @@ function App() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const { uploadId, urls: partUrls, totalParts, partSize } = startRes;
|
const { uploadId, urls: partUrls, totalParts, partSize } = startRes;
|
||||||
appendLog(3, `Upload ID: ${uploadId.slice(0, 32)}...`);
|
appendLog(6, `Upload ID: ${uploadId.slice(0, 32)}...`);
|
||||||
appendLog(3, `File hash: ${fileHash}`);
|
appendLog(6, `File hash: ${fileHash}`);
|
||||||
appendLog(3, `File size: ${fileSizeMB} MB`);
|
appendLog(6, `File size: ${fileSizeMB} MB`);
|
||||||
appendLog(3, `Parts: ${totalParts}`);
|
appendLog(6, `Parts: ${totalParts}`);
|
||||||
updateStep(3, { status: "done", detail: `${totalParts} parts` });
|
updateStep(6, { status: "done", detail: `${totalParts} parts` });
|
||||||
|
|
||||||
// ─── Step 4: Upload parts ───────────────────────────────────────
|
// ─── Step 7: Upload parts ───────────────────────────────────────
|
||||||
updateStep(4, { status: "running", progress: { bytes: 0, totalBytes: fileSize } });
|
updateStep(7, { status: "running", progress: { bytes: 0, totalBytes: fileSize } });
|
||||||
|
|
||||||
// Use the partSize from the server response
|
// Use the partSize from the server response
|
||||||
const completedParts: { partNumber: number; etag: string }[] = [];
|
const completedParts: { partNumber: number; etag: string }[] = [];
|
||||||
@@ -376,7 +407,7 @@ function App() {
|
|||||||
partSize,
|
partSize,
|
||||||
totalParts,
|
totalParts,
|
||||||
(partBytes) => {
|
(partBytes) => {
|
||||||
updateStep(4, {
|
updateStep(7, {
|
||||||
status: "running",
|
status: "running",
|
||||||
progress: { bytes: prevPartsBytes + partBytes, totalBytes: fileSize },
|
progress: { bytes: prevPartsBytes + partBytes, totalBytes: fileSize },
|
||||||
});
|
});
|
||||||
@@ -403,14 +434,14 @@ function App() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateStep(4, {
|
updateStep(7, {
|
||||||
status: "done",
|
status: "done",
|
||||||
detail: `${fileSizeMB} MB uploaded`,
|
detail: `${fileSizeMB} MB uploaded`,
|
||||||
progress: undefined,
|
progress: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
// ─── Step 5: Complete ────────────────────────────────────────────
|
// ─── Step 8: Complete ────────────────────────────────────────────
|
||||||
updateStep(5, { status: "running" });
|
updateStep(8, { status: "running" });
|
||||||
|
|
||||||
await apiPost(
|
await apiPost(
|
||||||
`${BASE_URL}/api/uploads/complete`,
|
`${BASE_URL}/api/uploads/complete`,
|
||||||
@@ -422,11 +453,11 @@ function App() {
|
|||||||
authHeaders(token)
|
authHeaders(token)
|
||||||
);
|
);
|
||||||
|
|
||||||
appendLog(5, `Key: ${UPLOAD_KEY}`);
|
appendLog(8, `Key: ${UPLOAD_KEY}`);
|
||||||
updateStep(5, { status: "done" });
|
updateStep(8, { status: "done" });
|
||||||
|
|
||||||
// ─── Step 6: Upload install-galaxy.sh ────────────────────────────
|
// ─── Step 9: Upload install-galaxy.sh ────────────────────────────
|
||||||
updateStep(6, { status: "running" });
|
updateStep(9, { status: "running" });
|
||||||
|
|
||||||
const installScriptPath = path.join(WORKSPACE_ROOT, "script", "install-galaxy.sh");
|
const installScriptPath = path.join(WORKSPACE_ROOT, "script", "install-galaxy.sh");
|
||||||
const scriptFileSize = statSync(installScriptPath).size;
|
const scriptFileSize = statSync(installScriptPath).size;
|
||||||
@@ -446,7 +477,7 @@ function App() {
|
|||||||
const scriptCompletedParts: { partNumber: number; etag: string }[] = [];
|
const scriptCompletedParts: { partNumber: number; etag: string }[] = [];
|
||||||
let scriptBytesUploaded = 0;
|
let scriptBytesUploaded = 0;
|
||||||
|
|
||||||
updateStep(6, { status: "running", progress: { bytes: 0, totalBytes: scriptFileSize } });
|
updateStep(9, { status: "running", progress: { bytes: 0, totalBytes: scriptFileSize } });
|
||||||
|
|
||||||
for (const part of scriptStartRes.urls) {
|
for (const part of scriptStartRes.urls) {
|
||||||
const prevBytes = scriptBytesUploaded;
|
const prevBytes = scriptBytesUploaded;
|
||||||
@@ -457,7 +488,7 @@ function App() {
|
|||||||
scriptStartRes.partSize,
|
scriptStartRes.partSize,
|
||||||
scriptStartRes.totalParts,
|
scriptStartRes.totalParts,
|
||||||
(partBytes) => {
|
(partBytes) => {
|
||||||
updateStep(6, {
|
updateStep(9, {
|
||||||
status: "running",
|
status: "running",
|
||||||
progress: { bytes: prevBytes + partBytes, totalBytes: scriptFileSize },
|
progress: { bytes: prevBytes + partBytes, totalBytes: scriptFileSize },
|
||||||
});
|
});
|
||||||
@@ -492,8 +523,8 @@ function App() {
|
|||||||
authHeaders(token)
|
authHeaders(token)
|
||||||
);
|
);
|
||||||
|
|
||||||
appendLog(6, `Key: ${INSTALL_SCRIPT_KEY}`);
|
appendLog(9, `Key: ${INSTALL_SCRIPT_KEY}`);
|
||||||
updateStep(6, { status: "done", detail: `${(scriptFileSize / 1024).toFixed(1)} KB`, progress: undefined });
|
updateStep(9, { status: "done", detail: `${(scriptFileSize / 1024).toFixed(1)} KB`, progress: undefined });
|
||||||
|
|
||||||
// Cleanup zip
|
// Cleanup zip
|
||||||
execSync(`rm -f "${zipPath}"`, { stdio: "pipe" });
|
execSync(`rm -f "${zipPath}"`, { stdio: "pipe" });
|
||||||
@@ -542,4 +573,4 @@ function App() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
render(<App />);
|
render(<App />);
|
||||||
|
|||||||
@@ -150,8 +150,12 @@ function StepLine({ step }: { step: Step }) {
|
|||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const [steps, setSteps] = useState<Step[]>([
|
const [steps, setSteps] = useState<Step[]>([
|
||||||
{ label: "Build Galaxy", status: "pending" },
|
{ label: "Check working directory", status: "pending" },
|
||||||
|
{ label: "Pull current branch", status: "pending" },
|
||||||
|
{ label: "Clean Cargo build artifacts", status: "pending" },
|
||||||
|
{ label: "Bundle Galaxy", status: "pending" },
|
||||||
{ label: "Copy to /Applications", status: "pending" },
|
{ label: "Copy to /Applications", status: "pending" },
|
||||||
|
{ label: "Launch Galaxy", status: "pending" },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const updateStep = useCallback((index: number, update: Partial<Step>) => {
|
const updateStep = useCallback((index: number, update: Partial<Step>) => {
|
||||||
@@ -172,48 +176,74 @@ function App() {
|
|||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
const appName = "Galaxy.app";
|
const appName = "Galaxy.app";
|
||||||
const appCrateDir = path.join(WORKSPACE_ROOT, "app");
|
|
||||||
const bundleDir = path.join(WORKSPACE_ROOT, "target/debug/bundle/osx");
|
const bundleDir = path.join(WORKSPACE_ROOT, "target/debug/bundle/osx");
|
||||||
const appPath = path.join(bundleDir, appName);
|
const appPath = path.join(bundleDir, appName);
|
||||||
const destPath = path.join("/Applications", appName);
|
const destPath = path.join("/Applications", appName);
|
||||||
|
|
||||||
// ─── Step 0: Build ──────────────────────────────────────────────
|
// ─── Step 0: Check working directory ───────────────────────────
|
||||||
updateStep(0, { status: "running" });
|
updateStep(0, { status: "running" });
|
||||||
|
await runCommandStreaming(
|
||||||
const buildCmd = "cargo bundle --bin galaxy-oss";
|
`if [ -n "$(git status --porcelain)" ]; then git status --short; exit 1; fi`,
|
||||||
|
WORKSPACE_ROOT,
|
||||||
await runCommandStreaming(buildCmd, appCrateDir, (line) => appendLog(0, line));
|
(line) => appendLog(0, line)
|
||||||
|
);
|
||||||
updateStep(0, { status: "done" });
|
updateStep(0, { status: "done" });
|
||||||
|
|
||||||
// ─── Step 1: Copy to /Applications ─────────────────────────────
|
// ─── Step 1: Pull current branch ────────────────────────────────
|
||||||
updateStep(1, { status: "running" });
|
updateStep(1, { status: "running" });
|
||||||
|
const branch = execSync("git branch --show-current", {
|
||||||
|
cwd: WORKSPACE_ROOT,
|
||||||
|
encoding: "utf8",
|
||||||
|
}).trim();
|
||||||
|
if (!branch) throw new Error("Cannot install from a detached HEAD");
|
||||||
|
await runCommandStreaming(
|
||||||
|
`git pull --ff-only origin "${branch}"`,
|
||||||
|
WORKSPACE_ROOT,
|
||||||
|
(line) => appendLog(1, line)
|
||||||
|
);
|
||||||
|
updateStep(1, { status: "done", detail: branch });
|
||||||
|
|
||||||
|
// ─── Step 2: Clean ──────────────────────────────────────────────
|
||||||
|
updateStep(2, { status: "running" });
|
||||||
|
await runCommandStreaming("cargo clean", WORKSPACE_ROOT, (line) => appendLog(2, line));
|
||||||
|
updateStep(2, { status: "done" });
|
||||||
|
|
||||||
|
// ─── Step 3: Bundle ─────────────────────────────────────────────
|
||||||
|
updateStep(3, { status: "running" });
|
||||||
|
await runCommandStreaming(
|
||||||
|
"cargo bundle --bin galaxy-oss --package galaxy",
|
||||||
|
WORKSPACE_ROOT,
|
||||||
|
(line) => appendLog(3, line)
|
||||||
|
);
|
||||||
|
updateStep(3, { status: "done" });
|
||||||
|
|
||||||
|
// ─── Step 4: Copy to /Applications ─────────────────────────────
|
||||||
|
updateStep(4, { status: "running" });
|
||||||
|
|
||||||
if (!fs.existsSync(appPath)) {
|
if (!fs.existsSync(appPath)) {
|
||||||
throw new Error(`Built app not found at ${appPath}`);
|
throw new Error(`Built app not found at ${appPath}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
await stopApp("Galaxy", (line) => appendLog(1, line));
|
await stopApp("Galaxy", (line) => appendLog(4, line));
|
||||||
|
|
||||||
if (fs.existsSync(destPath)) {
|
if (fs.existsSync(destPath)) {
|
||||||
appendLog(1, `Removing existing ${destPath}`);
|
appendLog(4, `Removing existing ${destPath}`);
|
||||||
execSync(`rm -rf "${destPath}"`, { stdio: "pipe" });
|
execSync(`rm -rf "${destPath}"`, { stdio: "pipe" });
|
||||||
}
|
}
|
||||||
|
|
||||||
appendLog(1, `Copying ${appPath} → ${destPath}`);
|
appendLog(4, `Copying ${appPath} → ${destPath}`);
|
||||||
await runCommandStreaming(
|
await runCommandStreaming(
|
||||||
`ditto "${appPath}" "${destPath}"`,
|
`ditto "${appPath}" "${destPath}"`,
|
||||||
WORKSPACE_ROOT,
|
WORKSPACE_ROOT,
|
||||||
(line) => appendLog(1, line)
|
(line) => appendLog(4, line)
|
||||||
);
|
);
|
||||||
|
|
||||||
updateStep(1, { status: "done", detail: destPath });
|
updateStep(4, { status: "done", detail: destPath });
|
||||||
|
|
||||||
// ─── Step 2: Launch ────────────────────────────────────────────
|
// ─── Step 5: Launch ────────────────────────────────────────────
|
||||||
setSteps((prev) => [...prev, { label: "Launch Galaxy", status: "running" }]);
|
updateStep(5, { status: "running" });
|
||||||
execSync(`open "${destPath}"`, { stdio: "ignore" });
|
execSync(`open "${destPath}"`, { stdio: "ignore" });
|
||||||
setSteps((prev) =>
|
updateStep(5, { status: "done" });
|
||||||
prev.map((s, i) => (i === 2 ? { ...s, status: "done" } : s))
|
|
||||||
);
|
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
setSteps((prev) =>
|
setSteps((prev) =>
|
||||||
prev.map((s) =>
|
prev.map((s) =>
|
||||||
|
|||||||
Executable
+7
@@ -0,0 +1,7 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Compatibility entrypoint for building and uploading Galaxy to Hermes.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
exec "$SCRIPT_DIR/build-and-deploy-hermes.sh" "$@"
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
#
|
#
|
||||||
# install-galaxy.sh — Download, sign, and install Galaxy.app on macOS.
|
# install-galaxy.sh — Download and install Galaxy.app on macOS.
|
||||||
#
|
#
|
||||||
# Usage:
|
# Usage:
|
||||||
# curl -fsSL https://mng-web-sharing.mini-games.tv/wst-data/ryan-share/galaxy/install-galaxy.sh | bash
|
# curl -fsSL https://mng-web-sharing.mini-games.tv/wst-data/ryan-share/galaxy/install-galaxy.sh | bash
|
||||||
@@ -44,15 +44,9 @@ if [[ ! -d "$TMP_DIR/$APP_NAME" ]]; then
|
|||||||
fail "$APP_NAME not found after extraction."
|
fail "$APP_NAME not found after extraction."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ---------- 3. Clear quarantine & ad-hoc sign ----------
|
# ---------- 3. Clear quarantine ----------
|
||||||
info "Clearing quarantine attributes..."
|
info "Removing the macOS quarantine attribute..."
|
||||||
/usr/bin/xattr -cr "$TMP_DIR/$APP_NAME" || fail "Failed to clear quarantine attributes."
|
/usr/bin/xattr -dr com.apple.quarantine "$TMP_DIR/$APP_NAME" 2>/dev/null || true
|
||||||
|
|
||||||
info "Ad-hoc code signing..."
|
|
||||||
/usr/bin/codesign --force --deep --sign - "$TMP_DIR/$APP_NAME" || fail "Code signing failed."
|
|
||||||
|
|
||||||
info "Verifying code signature..."
|
|
||||||
/usr/bin/codesign --verify --deep --strict --verbose=2 "$TMP_DIR/$APP_NAME" || fail "Code signature verification failed."
|
|
||||||
|
|
||||||
# ---------- 4. Kill, remove, install, launch ----------
|
# ---------- 4. Kill, remove, install, launch ----------
|
||||||
info "Stopping any running Galaxy processes..."
|
info "Stopping any running Galaxy processes..."
|
||||||
@@ -66,9 +60,6 @@ info "Staging $APP_NAME in $INSTALL_DIR..."
|
|||||||
rm -rf "$STAGED_APP"
|
rm -rf "$STAGED_APP"
|
||||||
cp -R "$TMP_DIR/$APP_NAME" "$STAGED_APP" || fail "Failed to copy $APP_NAME to $INSTALL_DIR."
|
cp -R "$TMP_DIR/$APP_NAME" "$STAGED_APP" || fail "Failed to copy $APP_NAME to $INSTALL_DIR."
|
||||||
|
|
||||||
/usr/bin/codesign --verify --deep --strict --verbose=2 "$STAGED_APP" ||
|
|
||||||
fail "Installed application signature verification failed."
|
|
||||||
|
|
||||||
if [[ -d "$INSTALLED_APP" ]]; then
|
if [[ -d "$INSTALLED_APP" ]]; then
|
||||||
info "Removing existing $INSTALLED_APP..."
|
info "Removing existing $INSTALLED_APP..."
|
||||||
rm -rf "$INSTALLED_APP"
|
rm -rf "$INSTALLED_APP"
|
||||||
|
|||||||
Reference in New Issue
Block a user