Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
7491241
Rewrite packaging script for pre-built CF deploy
norman-abramovitz Mar 6, 2026
b79a8b4
Produce amd64 and arm64 CF deploy zips
norman-abramovitz Mar 6, 2026
8614e44
Add GOOS to package output naming
norman-abramovitz Mar 7, 2026
5be0336
Improve e2e test portability
norman-abramovitz Mar 7, 2026
735f1c0
Add encrypt/decrypt scripts for e2e secrets
norman-abramovitz Mar 7, 2026
4a48e3d
Add test for timestamp visibility across layouts
norman-abramovitz Mar 7, 2026
2040bff
Show timestamps in all home page layouts
norman-abramovitz Mar 7, 2026
26ab68b
Fix layout signal propagation on home page
norman-abramovitz Mar 7, 2026
2c68b86
Show Routes metric in two-column home layout
norman-abramovitz Mar 7, 2026
00a5dfb
Keep metric tiles on single horizontal row
norman-abramovitz Mar 7, 2026
60c8094
Reduce sidebar width in multi-column layout
norman-abramovitz Mar 7, 2026
95f3200
Adjust recent apps row count for two-column
norman-abramovitz Mar 7, 2026
3d66bf7
Add columnSpan support for home cards
norman-abramovitz Mar 7, 2026
1214c78
Improve compact app card text overflow
norman-abramovitz Mar 7, 2026
6f1ed57
Add home page architecture documentation
norman-abramovitz Mar 7, 2026
a58d7ce
Fix endpoint page icon centering
norman-abramovitz Mar 7, 2026
178d5c6
Rename toggle to Show connected endpoints
norman-abramovitz Mar 7, 2026
a808d45
Fix home page first-load card rendering
norman-abramovitz Mar 7, 2026
0cabee6
Sort home page cards by render priority
norman-abramovitz Mar 7, 2026
d95ed8b
Stretch recent apps list to fill card width
norman-abramovitz Mar 7, 2026
67c0658
Add plugin architecture documentation
norman-abramovitz Mar 8, 2026
0c805e9
Add backend plugin config file
norman-abramovitz Mar 8, 2026
1b47781
Add go generate for plugin imports
norman-abramovitz Mar 8, 2026
1d4991b
Wire go generate into build targets
norman-abramovitz Mar 8, 2026
5c8fdb5
Read plugin list from backend config
norman-abramovitz Mar 8, 2026
363e8ec
Update plugin architecture documentation
norman-abramovitz Mar 8, 2026
d81c89e
Support stratos.yaml backend override in prebuild
norman-abramovitz Mar 8, 2026
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: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ build-frontend-dev:
build-backend:
@echo "$(BLUE)🔨 Building backend for $(CURRENT_PLATFORM)...$(NC)"
@mkdir -p $(BIN_DIR)
cd src/jetstream && go generate ./...
cd src/jetstream && \
go build \
-ldflags "-X main.appVersion=$(VERSION) -X main.buildDate=$(BUILD_DATE) -X main.gitCommit=$(GIT_COMMIT)" \
Expand Down
37 changes: 28 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,23 +159,42 @@ Note: `sgs` creates security groups the first time, upgrades do not use `sgs`.

## Packaging

Golang is required, and version 1.21 is recommended as this is the version used by the Stratos build system.
Requires `node`, `go`, and `zip`.

When you want to build the `4.8.1` tag in
[Stratos UI releases](https://github.com/cloudfoundry/stratos/releases),
run this command:
Build and package for all targets (linux/amd64, linux/arm64):

```bash
./bin/package
bin/package
```
OR to package a specific tag

To skip the build step and package from existing artifacts:

```bash
bin/package --skip-build
```

To override the version (default: from `package.json`):

```bash
VERSION="4.8.1" bin/package
```

This produces per-target zips in `dist/`:

```
dist/stratos-cf-<version>-<os>-<arch>.zip
```

Deploy with:

```bash
TAG="4.8.1" ./bin/package
cf push -f dist/cf-package-<os>-<arch>/manifest.yml \
-p dist/stratos-cf-<version>-<os>-<arch>.zip
```

### NOTE
The original code for this feature can be found in the
[Orange Cloud foundry Github Repository](https://github.com/orange-cloudfoundry/stratos-ui-cf-packager/).
The original packaging code was based on work from the
[Orange Cloud Foundry Github Repository](https://github.com/orange-cloudfoundry/stratos-ui-cf-packager/).
Many thanks to Benjamin & Arthur, we appreciate you both!

## License
Expand Down
304 changes: 180 additions & 124 deletions bin/package
Original file line number Diff line number Diff line change
@@ -1,134 +1,190 @@
#!/usr/bin/env bash
# shellcheck disable=SC2317

set -xeuo pipefail

declare git_url git_tag work_dir
declare -x TAG NODE_VERSION TMP_DIR

git_url="https://github.com/cloudfoundry/stratos.git"
git_tag="${TAG:-develop}"
work_dir="${PWD}"
NODE_VERSION="${NODE_VERISON:-24.10.0}"
NODE_SHA2="${NODE_SHA2:-TBD_NEED_TO_LOOKUP_FROM_CF_BUILDPACKS}"
TMP_DIR=/tmp

node::install() {
local download_file
download_file="${TMP_DIR}/node${NODE_VERSION}.tar.gz"

export node_install_dir="/tmp/node${NODE_VERSION}"
#export node_dir="${node_install_dir}/node-v${NODE_VERSION}-linux-x64"

mkdir -p "${node_install_dir}"

if [[ ! -f "${node_install_dir}/bin/node" ]]; then
# - name: node
# version: 20.13.1
# uri: https://buildpacks.cloudfoundry.org/dependencies/node/node_20.13.1_linux_x64_cflinuxfs4_71ec5c92.tgz
# sha256: 71ec5c92b35770170dad21ff65130f3e4201e8a0bcd32986e5dcf32b57f379e6
# cf_stacks:
# - cflinuxfs4
# source: https://nodejs.org/dist/v20.13.1/node-v20.13.1.tar.gz
# source_sha256: a85ee53aa0a5c2f5ca94fa414cdbceb91eb7d18a77fc498358512c14cc6c6991

URL=https://buildpacks.cloudfoundry.org/dependencies/node/node_${NODE_VERSION}_linux_x64_cflinuxfs4_71ec5c92.tgz

echo "-----> Download Nodejs ${NODE_VERSION}"
curl -s -L --retry 15 --retry-delay 2 "$URL" -o "${download_file}"

DOWNLOAD_SHA2=$(sha256sum "${download_file}" | cut -d ' ' -f 1)

if [[ ${DOWNLOAD_SHA2} != "${NODE_SHA2}" ]]; then
echo " **ERROR** MD5 mismatch: got $DOWNLOAD_SHA2 expected $NODE_SHA2"
exit 1
fi

tar xzf "${download_file}" -C "${node_install_dir}"
rm "${download_file}"
#
# Package Stratos for Cloud Foundry deployment.
#
# Builds the frontend and backend for all platforms, then produces
# per-architecture zips deployable with:
# cf push -f dist/cf-package-<os>-<arch>/manifest.yml -p dist/stratos-cf-<version>-<os>-<arch>.zip
#
# Usage:
# bin/package # build + package
# bin/package --skip-build # package from existing build artifacts
#
# Environment:
# VERSION - override version (default: from package.json)

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"

cd "${ROOT_DIR}"

VERSION="${VERSION:-$(node -p "require('./package.json').version" 2>/dev/null || echo "dev")}"
SKIP_BUILD="${1:-}"

DIST_DIR="${ROOT_DIR}/dist"
GOOS="linux"
CF_TARGETS=("${GOOS}:amd64" "${GOOS}:arm64")

log() { echo "-----> $1"; }
error() { echo "ERROR: $1" >&2; exit 1; }

# -------------------------------------------------------------------
# Preflight checks
# -------------------------------------------------------------------
preflight() {
local missing=()
command -v node >/dev/null || missing+=(node)
command -v go >/dev/null || missing+=(go)
command -v zip >/dev/null || missing+=(zip)

if [[ ${#missing[@]} -gt 0 ]]; then
error "Required tools not found: ${missing[*]}"
fi

if [[ ! -f "${node_install_dir}/bin/node" ]]; then
echo " **ERROR** Could not download nodejs"
exit 1
}

# -------------------------------------------------------------------
# Build everything via Makefile
# -------------------------------------------------------------------
build() {
if [[ "${SKIP_BUILD}" == "--skip-build" ]]; then
log "Skipping build (--skip-build)"
return
fi

export NODE_HOME="${node_install_dir}"

log "Building frontend and backend for all platforms..."
make build-frontend
make build-backend-all
}

# -------------------------------------------------------------------
# Find the frontend build output directory
# -------------------------------------------------------------------
find_ui_source() {
if [[ -d "${DIST_DIR}/browser" ]]; then
echo "${DIST_DIR}/browser"
return
fi
if [[ -d "${DIST_DIR}/stratos" ]]; then
echo "${DIST_DIR}/stratos"
return
fi
for item in "${DIST_DIR}"/*; do
base="$(basename "$item")"
case "${base}" in
jetstream*|cf-package*|release|bin|"stratos-cf-"*) continue ;;
esac
if [[ -d "$item" ]]; then
echo "$item"
return
fi
done
error "Frontend build output not found in ${DIST_DIR}/"
}

# -------------------------------------------------------------------
# Stage and archive one architecture
# -------------------------------------------------------------------
package_target() {
local os=$1
local arch=$2
local binary="${DIST_DIR}/bin/jetstream-${os}-${arch}"
local pkg_dir="${DIST_DIR}/cf-package-${os}-${arch}"
local zip_file="${DIST_DIR}/stratos-cf-${VERSION}-${os}-${arch}.zip"

if [[ ! -f "${binary}" ]]; then
error "Backend binary not found: ${binary}"
fi

log "Staging CF package (${os}/${arch})..."
rm -rf "${pkg_dir}"
mkdir -p "${pkg_dir}"

if [[ -z ${USE_LOCAL:-""} ]] ; then
# Backend binary
cp "${binary}" "${pkg_dir}/jetstream"
chmod +x "${pkg_dir}/jetstream"

git clone "${git_url}" stratos-ui || true
# Frontend assets — backend serves from ui/
local ui_src
ui_src="$(find_ui_source)"
cp -r "${ui_src}" "${pkg_dir}/ui"

if [[ -n ${git_tag} ]]; then
pushd stratos-ui
git checkout "${git_tag}"
export stratos_version="${git_tag}"
popd
# Config
cp "${ROOT_DIR}/deploy/cloud-foundry/config.properties" "${pkg_dir}/"

# Plugins
if [[ -f "${ROOT_DIR}/src/jetstream/plugins.yaml" ]]; then
cp "${ROOT_DIR}/src/jetstream/plugins.yaml" "${pkg_dir}/"
fi

# User invite templates
if [[ -d "${ROOT_DIR}/src/jetstream/templates" ]]; then
cp -r "${ROOT_DIR}/src/jetstream/templates" "${pkg_dir}/templates"
fi
else
echo "Using local checked out copy on stratos-ui"
fi

if [[ -n ${VERSION:-""} ]] ; then
export stratos_version="${VERSION}" # Will be tagged on publish in Concourse
fi

exit_trap() {
# See: install_nodejs.sh
[[ -d "${TMP_DIR}/node${NODE_VERSION}" ]] && rm -rf "${TMP_DIR}/node${NODE_VERSION}"
[[ -f "${TMP_DIR}/node${NODE_VERSION}.tar.gz" ]] && rm -rf "${TMP_DIR}/node${NODE_VERSION}.tar.gz"
true

# Procfile for CF
echo "web: ./jetstream" > "${pkg_dir}/Procfile"

# CF manifest for pre-built package
cat > "${pkg_dir}/manifest.yml" <<MANIFEST
applications:
- name: console
memory: 1512M
disk_quota: 1024M
timeout: 180
buildpack: binary_buildpack
health-check-type: port
command: ./jetstream
# env:
# Override CF API endpoint URL inferred from VCAP_APPLICATION env
# CF_API_URL: https://CLOUD_FOUNDRY_API_ENDPOINT
# Force the console to use secured communication with the Cloud Foundry API endpoint
# CF_API_FORCE_SECURE: true
# Turn on backend debugging
# LOG_LEVEL: debug
MANIFEST

# Create zip
log "Creating ${zip_file}..."
rm -f "${zip_file}"
cd "${pkg_dir}"
zip -r "${zip_file}" . -x '*.git*' '*.DS_Store'
cd "${ROOT_DIR}"
}

# -------------------------------------------------------------------
# Summary
# -------------------------------------------------------------------
summary() {
echo ""
log "Package complete!"
echo " Version: ${VERSION}"
echo ""
for target in "${CF_TARGETS[@]}"; do
local os="${target%%:*}"
local arch="${target##*:}"
local zip_file="${DIST_DIR}/stratos-cf-${VERSION}-${os}-${arch}.zip"
if [[ -f "${zip_file}" ]]; then
echo " ${os}/${arch}: ${zip_file} ($(du -h "${zip_file}" | cut -f1))"
fi
done
echo ""
echo "Deploy with:"
echo " cf push -f dist/cf-package-<os>-<arch>/manifest.yml -p dist/stratos-cf-${VERSION}-<os>-<arch>.zip"
echo ""
}
trap exit_trap EXIT

if ! which npm > /dev/null; then
node::install
export PATH="${NODE_HOME}/bin:$PATH"
else
npm_location="$(which npm)"
export NODE_HOME="${npm_location%%/bin/npm}"
fi

mkdir -p cache
build_dir="${work_dir}/stratos-ui"

# Fix the "authenticity of host can't be established" error during build
#ssh-keyscan "bitbucket.org" >> ~/.ssh/known_hosts

# prebuild ui
cd stratos-ui
if [[ -n "${stratos_version:-""}" ]]; then
sed -i package.json -e 's/"version": ".*",$/"version": "'"$stratos_version"'",/'
fi
npm install --legacy-peer-deps
npm run prebuild-ui
rm -Rf ./dist

# Actually build Stratos
bash -x deploy/cloud-foundry/build.sh "${build_dir}" "${work_dir}/cache"
cd "${work_dir}"

# Remove build artifacts (node_modules & bower_components)
if [[ -d "${build_dir}/node_modules" ]]; then
rm -rf "${build_dir}/node_modules"
fi

if [[ -d "${build_dir}/bower_components" ]]; then
rm -rf "${build_dir}/bower_components"
fi

echo "web: ./deploy/cloud-foundry/start.sh" > "${build_dir}/Procfile"

ls -lah "${build_dir}"
cd "${build_dir}"
package_version="${stratos_version:-"dev-$(date +%Y%m%d%H%M%S)"}"
if [[ -n ${RELEASE_DIR:-""} ]] ; then
zip -r -x@exclude.lst "${work_dir}/${RELEASE_DIR}/stratos-ui-${package_version}.zip" ./*
else
zip -r -x@exclude.lst "${work_dir}/stratos-ui-${package_version}.zip" ./*
fi
cd "${work_dir}"

exit 0

# -------------------------------------------------------------------
# Main
# -------------------------------------------------------------------
preflight
build

for target in "${CF_TARGETS[@]}"; do
os="${target%%:*}"
arch="${target##*:}"
package_target "${os}" "${arch}"
done

summary
Loading
Loading