Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,6 @@ jobs:
-v /etc/ssl/certs/ca-certificates.crt:/etc/ssl/certs/ca-certificates.crt:ro \
-e TZ="America/New_York" \
-e COMPOSE_VERSION="$COMPOSE_VERSION" \
-e ACE_VERSION="$ACE_VERSION" \
-e OUTPUT_FOLDER="/mnt/output" \
-e PKG_VERSION="${VERSION}" \
-e PKG_BUILD="${BUILD}" \
Expand Down
14 changes: 3 additions & 11 deletions build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

.DESCRIPTION
This script runs a Slackware Docker container to build the .txz package.
It downloads Docker Compose, Compose Switch, and Ace Editor, then packages
It downloads Docker Compose and Compose Switch, then packages
everything together.

.PARAMETER Version
Expand All @@ -18,10 +18,7 @@
Skip running tests before building. Not recommended.

.PARAMETER ComposeVersion
Docker Compose version to include. Default: 2.40.3

.PARAMETER AceVersion
Ace Editor version to include. Default: 1.4.14
Docker Compose version to include. Default: 5.0.2

.EXAMPLE
./build.ps1
Expand All @@ -34,8 +31,7 @@ param(
[string]$Version,
[switch]$Dev,
[switch]$SkipTests,
[string]$ComposeVersion,
[string]$AceVersion
[string]$ComposeVersion
)

$ErrorActionPreference = "Stop"
Expand All @@ -60,11 +56,9 @@ $versionsFile = Join-Path $ScriptDir "versions.env"
if (Test-Path $versionsFile) {
Get-Content $versionsFile | ForEach-Object {
if ($_ -match '^COMPOSE_VERSION=(.+)$' -and -not $ComposeVersion) { $ComposeVersion = $Matches[1].Trim() }
if ($_ -match '^ACE_VERSION=(.+)$' -and -not $AceVersion) { $AceVersion = $Matches[1].Trim() }
}
}
if (-not $ComposeVersion) { $ComposeVersion = "5.0.2" }
if (-not $AceVersion) { $AceVersion = "1.43.5" }

# Generate dev version with timestamp if -Dev flag is used
if ($Dev) {
Expand Down Expand Up @@ -126,7 +120,6 @@ Write-Host "Generated temporary plugin manifest for build: $TempPluginPath" -For

Write-Host "Building compose.manager package v$Version (build $BuildNum)" -ForegroundColor Green
Write-Host " Docker Compose: v$ComposeVersion" -ForegroundColor Gray
Write-Host " Ace Editor: v$AceVersion" -ForegroundColor Gray
Write-Host ""

# Convert Windows paths to Docker-compatible paths
Expand Down Expand Up @@ -161,7 +154,6 @@ $dockerArgs = @(
"-v", "${HostCACert}:${ContainerCACert}:ro"
"-e", "TZ=America/New_York"
"-e", "COMPOSE_VERSION=$ComposeVersion"
"-e", "ACE_VERSION=$AceVersion"
"-e", "OUTPUT_FOLDER=/mnt/output"
"-e", "PKG_VERSION=$Version"
"-e", "PKG_BUILD=$BuildNum"
Expand Down
2 changes: 0 additions & 2 deletions build_in_docker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
[ -f "${SCRIPT_DIR}/versions.env" ] && source "${SCRIPT_DIR}/versions.env"
[ -z "$COMPOSE_VERSION" ] && COMPOSE_VERSION=5.0.2
[ -z "$ACE_VERSION" ] && ACE_VERSION=1.43.5
[ -z "$PKG_VERSION" ] && PKG_VERSION="$(date +%Y.%m.%d)"
[ -z "$PKG_BUILD" ] && PKG_BUILD="$(date +%H%M)"
docker run --rm --tmpfs /tmp \
-v "$PWD/archive:/mnt/output:rw" \
-e TZ="America/New_York" \
-e COMPOSE_VERSION="$COMPOSE_VERSION" \
-e ACE_VERSION="$ACE_VERSION" \
-e PKG_VERSION="$PKG_VERSION" \
-e PKG_BUILD="$PKG_BUILD" \
-e OUTPUT_FOLDER="/mnt/output" \
Expand Down
48 changes: 48 additions & 0 deletions compose.manager.plg
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
<!ENTITY packageURL "https://github.com/&github;/releases/download/v&version;/&packagefile;">
<!ENTITY pluginLOC "/boot/config/plugins/&name;">
<!ENTITY emhttpLOC "/usr/local/emhttp/plugins/&name;">
<!ENTITY aceVER "1.43.5">
<!ENTITY aceURL "https://github.com/ajaxorg/ace-builds/archive/refs/tags/v&aceVER;.zip">
]>

<PLUGIN name="&name;"
Expand Down Expand Up @@ -70,6 +72,52 @@ fi
<MD5>&packageMD5;</MD5>
</FILE>

<FILE Run="/bin/bash">
<INLINE>
# Download Ace editor if not already provided by Unraid (Unraid 7.0.0+ includes it via Dynamix)
ACE_DYNAMIX_PATH="/usr/local/emhttp/plugins/dynamix/javascript/ace/ace.js"
ACE_PLUGIN_DIR="&emhttpLOC;/javascript/ace"

if [ -f "$ACE_DYNAMIX_PATH" ]; then
echo "Ace editor found at $ACE_DYNAMIX_PATH (Unraid 7.0.0+), skipping download."
else
echo "Ace editor not found in Dynamix (pre-7.0.0 Unraid), downloading v&aceVER;..."
mkdir -p "$ACE_PLUGIN_DIR"
TMPDIR_ACE="/tmp/ace-install-$$"
mkdir -p "$TMPDIR_ACE"
WGET_CERT_OPTS=""
if [ ! -f /etc/ssl/certs/ca-certificates.crt ] &amp;&amp; [ ! -d /etc/ssl/certs ]; then
echo "WARNING: No system CA bundle found; downloading Ace with TLS verification disabled."
WGET_CERT_OPTS="--no-check-certificate"
fi
if wget $WGET_CERT_OPTS -q -O "$TMPDIR_ACE/ace.zip" "&aceURL;"; then
if unzip -q "$TMPDIR_ACE/ace.zip" \
"ace-builds-&aceVER;/src-min-noconflict/ace.js" \
"ace-builds-&aceVER;/src-min-noconflict/mode-yaml.js" \
"ace-builds-&aceVER;/src-min-noconflict/mode-sh.js" \
"ace-builds-&aceVER;/src-min-noconflict/theme-tomorrow.js" \
"ace-builds-&aceVER;/src-min-noconflict/theme-tomorrow_night.js" \
-d "$TMPDIR_ACE/extracted"; then
if cp "$TMPDIR_ACE/extracted/ace-builds-&aceVER;/src-min-noconflict/"*.js "$ACE_PLUGIN_DIR/"; then
if [ -f "$ACE_PLUGIN_DIR/ace.js" ]; then
echo "Ace editor v&aceVER; installed to $ACE_PLUGIN_DIR"
else
echo "WARNING: Ace editor files not found in $ACE_PLUGIN_DIR after install. Editor will lack syntax highlighting."
fi
else
echo "WARNING: Failed to copy Ace editor files. Editor will lack syntax highlighting."
fi
else
echo "WARNING: Failed to extract Ace editor archive. Editor will lack syntax highlighting."
fi
else
echo "WARNING: Failed to download Ace editor. The YAML/env editor will not have syntax highlighting."
fi
rm -rf "$TMPDIR_ACE"
fi
</INLINE>
</FILE>

<FILE Run="/bin/bash">
<INLINE>
# Use the new patch utility during install to cleanup and optionally apply patches
Expand Down
11 changes: 8 additions & 3 deletions source/compose.manager/compose.manager.settings.page
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ $ui_patch_help_class = $option_patch_ui ? "hidden" : "inline_help"; // hide help


$projects_exist = intval(shell_exec("ls -l " . $compose_root . " | grep ^d | wc -l")) != 0;

$acePath = file_exists('/usr/local/emhttp/plugins/dynamix/javascript/ace/ace.js')
? '/webGui/javascript/ace'
: '/plugins/compose.manager/javascript/ace';
?>
<link type="text/css" rel="stylesheet" href="<? autov('/webGui/styles/jquery.switchbutton.css') ?>">
<link type="text/css" rel="stylesheet" href="<? autov('/webGui/styles/jquery.filetree.css') ?>">
Expand Down Expand Up @@ -2496,7 +2500,7 @@ $projects_exist = intval(shell_exec("ls -l " . $compose_root . " | grep ^d | wc
<h3>Build &amp; Packaging</h3>
<ul>
<li>`pkg_build.sh` — packaging helper used when assembling plugin releases.</li>
<li><a href="https://github.com/ajaxorg/ace-builds" target="_blank" rel="noopener noreferrer">ace-builds</a> — source for the bundled Ace editor files.</li>
<li><a href="https://github.com/ajaxorg/ace-builds" target="_blank" rel="noopener noreferrer">ace-builds</a> — Ace editor (provided by Unraid 7.0.0+ via Dynamix; downloaded during install on older versions).</li>
</ul>
<p>If you maintain packaging scripts or upstream libraries we reference and would like a more explicit mention, let me know and I'll add it.</p>
</div>
Expand Down Expand Up @@ -2532,8 +2536,9 @@ $projects_exist = intval(shell_exec("ls -l " . $compose_root . " | grep ^d | wc
}
} catch (e) {}

// Fallback: fetch the bundled ace.js and attempt to extract a version string
$.get('/plugins/compose.manager/javascript/ace/ace.js', function(data) {
// Fallback: fetch ace.js from wherever it lives (Dynamix on 7.0.0+, plugin-local on older)
var aceJsPath = <?php echo json_encode($acePath); ?> + '/ace.js';
$.get(aceJsPath, function(data) {
var m = null;
// common patterns: ace.version = '1.4.12' or "version: '1.4.12'" or ace-builds-1.4.12
m = data.match(/ace\.version\s*=\s*['\"]([\w\.\-]+)['\"]/i) || data.match(/version\s*[:=]\s*['\"]([\w\.\-]+)['\"]/i) || data.match(/ace-builds[-_]?([\d\.\-]+)/i);
Expand Down
47 changes: 40 additions & 7 deletions source/compose.manager/php/compose_manager_main.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,15 +178,29 @@

</style>

<script src="/plugins/compose.manager/javascript/ace/ace.js" type="text/javascript"></script>
<?php
// Use Dynamix's bundled Ace if available (Unraid 7.0.0+), else fall back to our plugin-local copy
// (downloaded during install for pre-7.0.0 Unraid via the PLG post-install script)
$acePath = file_exists('/usr/local/emhttp/plugins/dynamix/javascript/ace/ace.js')
? '/webGui/javascript/ace'
: '/plugins/compose.manager/javascript/ace';
?>
<script src="<?php echo $acePath; ?>/ace.js" type="text/javascript"></script>
<script src="/plugins/compose.manager/javascript/js-yaml/js-yaml.min.js" type="text/javascript"></script>
<script src="/plugins/compose.manager/javascript/common.js" type="text/javascript"></script>
<script>
var compose_root = <?php echo json_encode($compose_root); ?>;
var caURL = "/plugins/compose.manager/php/exec.php";
var compURL = "/plugins/compose.manager/php/compose_util.php";
var aceTheme = <?php echo (in_array($theme, ['black', 'gray']) ? json_encode('ace/theme/tomorrow_night') : json_encode('ace/theme/tomorrow')); ?>;
var aceBasePath = <?php echo json_encode($acePath); ?>;
const icon_label = <?php echo json_encode($docker_label_icon); ?>;

// Configure Ace base path explicitly so it finds mode/theme files
// regardless of how the script URL was resolved
if (typeof ace !== 'undefined') {
ace.config.set('basePath', aceBasePath);
}
const webui_label = <?php echo json_encode($docker_label_webui); ?>;
const shell_label = <?php echo json_encode($docker_label_shell); ?>;

Expand Down Expand Up @@ -588,6 +602,10 @@ function updateModalOffset() {

// Initialize editor modal
function initEditorModal() {
if (typeof ace === 'undefined') {
console.warn('Compose Manager: Ace editor not available. Editor will open without syntax highlighting.');
return;
}
// Initialize Ace editors for compose and env tabs only
['compose', 'env'].forEach(function(type) {
var editor = ace.edit('editor-' + type);
Expand All @@ -600,6 +618,10 @@ function initEditorModal() {
wrap: true
});

// Disable workers to avoid loading worker-yaml.js / worker-sh.js —
// we already validate YAML client-side via js-yaml
editor.getSession().setUseWorker(false);

// Set mode based on type
if (type === 'env') {
editor.getSession().setMode('ace/mode/sh');
Expand Down Expand Up @@ -3292,6 +3314,15 @@ function toggleAllProfiles(checkbox) {
}

function openEditorModalByProject(project, projectName, initialTab) {
if (typeof ace === 'undefined') {
swal({
title: 'Editor Unavailable',
text: 'The Ace editor library could not be loaded. Please reload the page or verify the plugin installation.',
type: 'error'
});
return;
}

editorModal.currentProject = project;
editorModal.modifiedTabs = new Set();
editorModal.modifiedSettings = new Set();
Expand Down Expand Up @@ -3342,12 +3373,12 @@ function loadEditorFiles(project) {
if (data) {
var response = jQuery.parseJSON(data);
editorModal.originalContent['compose'] = response.content || '';
editorModal.editors['compose'].setValue(response.content || '', -1);
if (editorModal.editors['compose']) editorModal.editors['compose'].setValue(response.content || '', -1);
}
}).fail(function() {
var errorContent = '# Error loading file';
editorModal.originalContent['compose'] = errorContent;
editorModal.editors['compose'].setValue(errorContent, -1);
if (editorModal.editors['compose']) editorModal.editors['compose'].setValue(errorContent, -1);
})
);

Expand All @@ -3360,19 +3391,20 @@ function loadEditorFiles(project) {
if (data) {
var response = jQuery.parseJSON(data);
editorModal.originalContent['env'] = response.content || '';
editorModal.editors['env'].setValue(response.content || '', -1);
if (editorModal.editors['env']) editorModal.editors['env'].setValue(response.content || '', -1);
}
}).fail(function() {
var errorContent = '# Error loading file';
editorModal.originalContent['env'] = errorContent;
editorModal.editors['env'].setValue(errorContent, -1);
if (editorModal.editors['env']) editorModal.editors['env'].setValue(errorContent, -1);
})
);

// When all files are loaded
$.when.apply($, loadPromises).then(function() {
// Run validation on compose file
validateYaml('compose', editorModal.editors['compose'].getValue());
var composeContent = editorModal.editors['compose'] ? editorModal.editors['compose'].getValue() : (editorModal.originalContent['compose'] || '');
validateYaml('compose', composeContent);
}).fail(function() {
$('#editor-validation-compose').html('<i class="fa fa-exclamation-triangle editor-validation-icon"></i> Error loading some files').removeClass('valid').addClass('error');
});
Expand Down Expand Up @@ -3765,7 +3797,7 @@ function saveCurrentTab() {
// Brief feedback in validation panel
$('#editor-validation-' + currentTab).html('<i class="fa fa-check editor-validation-icon"></i> Saved!').removeClass('error warning').addClass('valid');
setTimeout(function() {
validateYaml(currentTab, editorModal.editors[currentTab].getValue());
if (editorModal.editors[currentTab]) validateYaml(currentTab, editorModal.editors[currentTab].getValue());
}, 1500);
} else {
$('#editor-validation-' + currentTab).html('<i class="fa fa-exclamation-triangle editor-validation-icon"></i> Save failed').removeClass('valid warning').addClass('error');
Expand All @@ -3776,6 +3808,7 @@ function saveCurrentTab() {
}

function saveTab(tabName, saveErrors) {
if (!editorModal.editors[tabName]) return Promise.reject('Editor not available');
var content = editorModal.editors[tabName].getValue();
var project = editorModal.currentProject;
var actionStr = null;
Expand Down
29 changes: 0 additions & 29 deletions source/pkg_build.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#!/bin/bash
[ -z "$OUTPUT_FOLDER" ] && echo "Output Folder not set" && exit 1
[ -z "$COMPOSE_VERSION" ] && echo "Compose Version not set" && exit 2
[ -z "$ACE_VERSION" ] && echo "ACE Version not set" && exit 4
[ -z "$PKG_VERSION" ] && echo "Package Version not set" && exit 5
[ -z "$PKG_BUILD" ] && PKG_BUILD=$(date +%H%M)
tmpdir=/tmp/tmp.$((RANDOM * 19318203981230 + 40))
Expand Down Expand Up @@ -88,33 +87,6 @@ run_quiet cp docker-compose-linux-x86_64 "$tmpdir/usr/lib/docker/cli-plugins/doc
run_quiet chmod -R +x "$tmpdir/usr/lib/docker/cli-plugins/"
run_quiet rm docker-compose-linux-x86_64

echo "Installing Ace Editor v${ACE_VERSION}..."
run_quiet mkdir -p "$tmpdir/usr/local/emhttp/plugins/compose.manager/javascript/ace/"
run_quiet wget $(wget_args) "https://github.com/ajaxorg/ace-builds/archive/refs/tags/v${ACE_VERSION}.zip"
run_quiet mkdir -p /tmp/ace

echo "Unpacking Ace Editor v${ACE_VERSION}..."
run_quiet unzip "v${ACE_VERSION}.zip" ace-builds-${ACE_VERSION}/src-min-noconflict/* -d "/tmp/ace"

echo "Copying Ace Editor files to package structure..."
run_quiet cp -RT "/tmp/ace/ace-builds-${ACE_VERSION}/src-min-noconflict" "$tmpdir/usr/local/emhttp/plugins/compose.manager/javascript/ace/"
# shellcheck disable=SC2086
run_quiet cp /tmp/ace/ace-builds-${ACE_VERSION}/src-min-noconflict/*yaml.js "$tmpdir/usr/local/emhttp/plugins/compose.manager/javascript/ace/" >> "$LOG_FILE" 2>&1 || :
# shellcheck disable=SC2086
run_quiet cp /tmp/ace/ace-builds-${ACE_VERSION}/src-min-noconflict/*text.js "$tmpdir/usr/local/emhttp/plugins/compose.manager/javascript/ace/" >> "$LOG_FILE" 2>&1 || :
# shellcheck disable=SC2086
run_quiet cp /tmp/ace/ace-builds-${ACE_VERSION}/src-min-noconflict/mode-sh.js "$tmpdir/usr/local/emhttp/plugins/compose.manager/javascript/ace/" >> "$LOG_FILE" 2>&1 || :

# The "Tomorrow" themes are used by default in the YAML editor, so we need to include those as well
# shellcheck disable=SC2086
run_quiet cp /tmp/ace/ace-builds-${ACE_VERSION}/src-min-noconflict/*tomorrow.js "$tmpdir/usr/local/emhttp/plugins/compose.manager/javascript/ace/" >> "$LOG_FILE" 2>&1 || :
# shellcheck disable=SC2086
run_quiet cp /tmp/ace/ace-builds-${ACE_VERSION}/src-min-noconflict/*tomorrow_night.js "$tmpdir/usr/local/emhttp/plugins/compose.manager/javascript/ace/" >> "$LOG_FILE" 2>&1 || :

# Set execute permissions for Ace Editor files
run_quiet chmod -R +x "$tmpdir/usr/local/emhttp/plugins/compose.manager/javascript/ace/"
run_quiet rm -R /tmp/ace
run_quiet rm "v${ACE_VERSION}.zip"

echo "Creating package description (slack-desc)..."
run_quiet mkdir -p $tmpdir/install
Expand Down Expand Up @@ -150,7 +122,6 @@ MD5=$(md5sum "$OUTPUT_FOLDER/compose.manager-${version}-noarch-${build}.txz")
{
echo "MD5: $MD5"
echo "Compose v${COMPOSE_VERSION}"
echo "Ace v${ACE_VERSION}"
echo ""
echo "MD5: $(echo "$MD5" | head -n1 | awk '{print $1;}')"
} >> "$OUTPUT_FOLDER/release_info"
Expand Down
1 change: 0 additions & 1 deletion versions.env
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
COMPOSE_VERSION=5.0.2
ACE_VERSION=1.43.5
Loading