'Generic Commit'
This commit is contained in:
@@ -9,12 +9,13 @@ defaults:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
strategy:
|
||||||
|
matrix:
|
||||||
|
platform:
|
||||||
|
- linux/amd64
|
||||||
|
- linux/arm64
|
||||||
|
runs-on: ${{ matrix.platform }}
|
||||||
steps:
|
steps:
|
||||||
- name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@v3
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Login to Gitea
|
- name: Login to Gitea
|
||||||
@@ -23,12 +24,48 @@ jobs:
|
|||||||
registry: gitea.jde.nz
|
registry: gitea.jde.nz
|
||||||
username: DoesntMatter
|
username: DoesntMatter
|
||||||
password: ${{ secrets.DOCKER_PUSH_TOKEN }}
|
password: ${{ secrets.DOCKER_PUSH_TOKEN }}
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
./build.sh
|
./build.sh
|
||||||
- name: Test
|
- name: Run Tests
|
||||||
run: |
|
run: |
|
||||||
./test.sh
|
./test.sh
|
||||||
- name: Publish
|
- name: Publish as Latest
|
||||||
run: |
|
run: |
|
||||||
SOS_WRITE_TOKEN=${{ secrets.SOS_WRITE_TOKEN }} ./publish.sh
|
# Only publish on main branch
|
||||||
|
if [ "$GITHUB_REF" = "refs/heads/main" ]; then
|
||||||
|
SOS_WRITE_TOKEN=${{ secrets.SOS_WRITE_TOKEN }} \
|
||||||
|
DOCKER_PUSH_TOKEN=${{ secrets.DOCKER_PUSH_TOKEN }} \
|
||||||
|
./publish.sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
create-manifest:
|
||||||
|
needs: [build]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Login to Gitea
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: gitea.jde.nz
|
||||||
|
username: DoesntMatter
|
||||||
|
password: ${{ secrets.DOCKER_PUSH_TOKEN }}
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y jq
|
||||||
|
|
||||||
|
- name: Create and push manifest list
|
||||||
|
run: |
|
||||||
|
# Only create manifest on main branch
|
||||||
|
if [ "$GITHUB_REF" = "refs/heads/main" ]; then
|
||||||
|
# Create the manifest list using the architecture-specific digests
|
||||||
|
docker manifest create gitea.jde.nz/public/simple-object-server:latest \
|
||||||
|
--amend gitea.jde.nz/public/simple-object-server:latest-x86_64 \
|
||||||
|
--amend gitea.jde.nz/public/simple-object-server:latest-aarch64
|
||||||
|
|
||||||
|
# Push the manifest list
|
||||||
|
docker manifest push gitea.jde.nz/public/simple-object-server:latest
|
||||||
|
|
||||||
|
echo "Manifest list created and pushed successfully"
|
||||||
|
fi
|
||||||
|
3
build.sh
3
build.sh
@@ -16,11 +16,10 @@ PROJECT="simple-object-server"
|
|||||||
export DOCKER_BUILDKIT=1
|
export DOCKER_BUILDKIT=1
|
||||||
|
|
||||||
docker build \
|
docker build \
|
||||||
-t "gitea.jde.nz/public/${PROJECT}-build:latest" \
|
-t "${PROJECT}-build" \
|
||||||
-f "${SCRIPT_DIR}/Dockerfile.dropshell-build" \
|
-f "${SCRIPT_DIR}/Dockerfile.dropshell-build" \
|
||||||
--build-arg PROJECT="${PROJECT}" \
|
--build-arg PROJECT="${PROJECT}" \
|
||||||
--build-arg CMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}" \
|
--build-arg CMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}" \
|
||||||
--output "${SCRIPT_DIR}/output" \
|
--output "${SCRIPT_DIR}/output" \
|
||||||
"${SCRIPT_DIR}"
|
"${SCRIPT_DIR}"
|
||||||
|
|
||||||
# --platform linux/amd64 \
|
|
||||||
|
82
publish.sh
82
publish.sh
@@ -6,69 +6,29 @@ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
|
|||||||
|
|
||||||
echo "Publishing simple-object-server to gitea.jde.nz/public/simple-object-server:latest"
|
echo "Publishing simple-object-server to gitea.jde.nz/public/simple-object-server:latest"
|
||||||
|
|
||||||
PROJECT="simple-object-server"
|
|
||||||
[[ -n $SOS_WRITE_TOKEN ]] || die "SOS_WRITE_TOKEN not specified"
|
|
||||||
|
|
||||||
# FUNCTIONS
|
|
||||||
function title() {
|
|
||||||
echo "----------------------------------------"
|
|
||||||
# Center the text
|
|
||||||
local text="$1"
|
|
||||||
local line_length=40
|
|
||||||
local text_length=${#text}
|
|
||||||
local padding=$(( (line_length - text_length) / 2 ))
|
|
||||||
printf "%*s%s%*s\n" $padding "" "$text" $padding ""
|
|
||||||
echo "----------------------------------------"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function die() {
|
function die() {
|
||||||
title "error: $1"
|
title "error: $1"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Create buildx builder if it doesn't exist
|
[[ -n $SOS_WRITE_TOKEN ]] || die "SOS_WRITE_TOKEN not specified"
|
||||||
if ! docker buildx ls | grep -q "${PROJECT}-multiarch"; then
|
|
||||||
docker buildx create --name ${PROJECT}-multiarch --use \
|
|
||||||
--driver-opt env.BUILDKIT_MAX_PARALLELISM=4
|
|
||||||
else
|
|
||||||
docker buildx use ${PROJECT}-multiarch
|
|
||||||
fi
|
|
||||||
|
|
||||||
function build() {
|
|
||||||
local PLATFORM="$1"
|
|
||||||
|
|
||||||
# convert linux/amd64 to linux-amd64, windows/amd64 to windows-amd64, etc.
|
rm -rf "${SCRIPT_DIR}/output"
|
||||||
local OSARCH="${PLATFORM//\//-}"
|
|
||||||
|
|
||||||
title "Building ${PROJECT} for ${PLATFORM}"
|
|
||||||
|
|
||||||
docker buildx build \
|
|
||||||
-t "gitea.jde.nz/public/${PROJECT}-build:latest" \
|
|
||||||
-f "${SCRIPT_DIR}/Dockerfile.dropshell-build" \
|
|
||||||
--build-arg PROJECT="${PROJECT}" \
|
|
||||||
--build-arg CMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}" \
|
|
||||||
--output "${SCRIPT_DIR}/output/${OSARCH}" \
|
|
||||||
--platform "${PLATFORM}" \
|
|
||||||
--cache-from type=local,src=/tmp/.buildx-cache \
|
|
||||||
--cache-to type=local,dest=/tmp/.buildx-cache,mode=max \
|
|
||||||
"${SCRIPT_DIR}"
|
|
||||||
|
|
||||||
mv "${SCRIPT_DIR}/output/${OSARCH}/${PROJECT}" "${SCRIPT_DIR}/output/${PROJECT}-${OSARCH}"
|
|
||||||
rm -rf "${SCRIPT_DIR}/output/${OSARCH}"
|
|
||||||
}
|
|
||||||
|
|
||||||
CMAKE_BUILD_TYPE="Release"
|
|
||||||
|
|
||||||
rm -rf "${SCRIPT_DIR}/output"
|
|
||||||
mkdir -p "${SCRIPT_DIR}/output"
|
mkdir -p "${SCRIPT_DIR}/output"
|
||||||
mkdir -p /tmp/.buildx-cache
|
|
||||||
|
|
||||||
build "linux/amd64"
|
export CMAKE_BUILD_TYPE="Release"
|
||||||
build "linux/arm64"
|
export PROJECT="simple-object-server"
|
||||||
|
|
||||||
[ -f "${SCRIPT_DIR}/output/${PROJECT}-linux-amd64" ] || die "${PROJECT}-linux-amd64 not found"
|
docker build \
|
||||||
[ -f "${SCRIPT_DIR}/output/${PROJECT}-linux-arm64" ] || die "${PROJECT}-linux-arm64 not found"
|
-t "${PROJECT}-build" \
|
||||||
|
-f "${SCRIPT_DIR}/Dockerfile.dropshell-build" \
|
||||||
|
--build-arg PROJECT="${PROJECT}" \
|
||||||
|
--build-arg CMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}" \
|
||||||
|
--output "${SCRIPT_DIR}/output" \
|
||||||
|
"${SCRIPT_DIR}"
|
||||||
|
|
||||||
|
[ -f ${SCRIPT_DIR}/output/simple-object-server ] || die "Build failed."
|
||||||
|
|
||||||
# uplaod to getbin.xyz
|
# uplaod to getbin.xyz
|
||||||
|
|
||||||
@@ -80,7 +40,19 @@ trap 'rm -rf "${SCRIPT_DIR}/temp"' EXIT
|
|||||||
curl -L -o "${SOS}" "https://getbin.xyz/sos"
|
curl -L -o "${SOS}" "https://getbin.xyz/sos"
|
||||||
chmod +x "${SOS}"
|
chmod +x "${SOS}"
|
||||||
|
|
||||||
"${SOS}" upload "getbin.xyz" "${SCRIPT_DIR}/output/${PROJECT}-linux-amd64" "${PROJECT}:amd64"
|
ARCH=$(uname -m)
|
||||||
"${SOS}" upload "getbin.xyz" "${SCRIPT_DIR}/output/${PROJECT}-linux-arm64" "${PROJECT}:arm64"
|
|
||||||
|
|
||||||
|
# upload arch-specific binary
|
||||||
|
"${SOS}" upload "getbin.xyz" "${SCRIPT_DIR}/output/${PROJECT}" "${PROJECT}:latest-${ARCH}"
|
||||||
|
|
||||||
|
# upload generic install script (ok if multiple times as we iterate through arch's)
|
||||||
"${SOS}" upload "getbin.xyz" "${SCRIPT_DIR}/install.sh" "simple-object-server-install:latest"
|
"${SOS}" upload "getbin.xyz" "${SCRIPT_DIR}/install.sh" "simple-object-server-install:latest"
|
||||||
|
|
||||||
|
# create and upload the arch-specific docker image
|
||||||
|
IMAGE_NAME="gitea.jde.nz/public/simple-object-server:latest-${ARCH}"
|
||||||
|
docker build \
|
||||||
|
-f "${SCRIPT_DIR}/Dockerfile.sos" \
|
||||||
|
-t "${IMAGE_NAME}" \
|
||||||
|
"${SCRIPT_DIR}"
|
||||||
|
|
||||||
|
docker push "${IMAGE_NAME}"
|
||||||
|
@@ -109,8 +109,24 @@ std::vector<SourceInfo> get_source_info_batch(const char* executable, const std:
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper function to get the program counter (return address) in a portable way
|
||||||
|
inline void* get_pc() {
|
||||||
|
void* pc;
|
||||||
|
#if defined(__aarch64__) || defined(__arm__)
|
||||||
|
// For ARM/AArch64, we can use the link register (x30 on AArch64, r14 on ARM)
|
||||||
|
#if defined(__aarch64__)
|
||||||
|
asm volatile ("mov %0, x30" : "=r" (pc));
|
||||||
|
#else
|
||||||
|
asm volatile ("mov %0, lr" : "=r" (pc));
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
// For x86/x86_64, use __builtin_return_address
|
||||||
|
pc = __builtin_return_address(0);
|
||||||
|
#endif
|
||||||
|
return pc;
|
||||||
|
}
|
||||||
|
|
||||||
void print_stacktrace() {
|
void print_stacktrace() {
|
||||||
// Simple stacktrace implementation that doesn't segfault
|
|
||||||
std::cerr << colors::yellow << "Stack trace:" << colors::reset << "\n";
|
std::cerr << colors::yellow << "Stack trace:" << colors::reset << "\n";
|
||||||
|
|
||||||
char exe_path[1024] = {0};
|
char exe_path[1024] = {0};
|
||||||
@@ -121,19 +137,29 @@ void print_stacktrace() {
|
|||||||
exe_path[count] = '\0';
|
exe_path[count] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get just a couple of stack frames safely
|
|
||||||
std::vector<void*> addresses;
|
std::vector<void*> addresses;
|
||||||
|
|
||||||
void* addr1 = __builtin_return_address(1); // assert_failed
|
// Get current frame pointer and return address
|
||||||
void* addr2 = __builtin_return_address(2); // caller of ASSERT
|
void* frame_ptr = __builtin_frame_address(0);
|
||||||
|
void* return_addr = get_pc();
|
||||||
|
|
||||||
// Adjust addresses to point to call site instead of return address
|
// Add current return address
|
||||||
// Subtract a small offset to get the call instruction instead of the return address
|
if (return_addr) {
|
||||||
if (addr1) {
|
addresses.push_back(return_addr);
|
||||||
addresses.push_back(static_cast<char*>(addr1) - 1);
|
|
||||||
}
|
}
|
||||||
if (addr2) {
|
|
||||||
addresses.push_back(static_cast<char*>(addr2) - 1);
|
// Try to walk up the stack if we have a valid frame pointer
|
||||||
|
if (frame_ptr) {
|
||||||
|
void** frame = static_cast<void**>(frame_ptr);
|
||||||
|
// Limit the number of frames to prevent potential issues
|
||||||
|
for (int i = 0; i < 5; ++i) {
|
||||||
|
// The return address is typically at frame[1]
|
||||||
|
if (frame[1] == nullptr) break;
|
||||||
|
addresses.push_back(frame[1]);
|
||||||
|
// Move to the next frame
|
||||||
|
if (frame[0] == nullptr) break;
|
||||||
|
frame = static_cast<void**>(frame[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addresses.empty()) {
|
if (addresses.empty()) {
|
||||||
@@ -144,18 +170,55 @@ void print_stacktrace() {
|
|||||||
// Get source info
|
// Get source info
|
||||||
std::vector<SourceInfo> results = get_source_info_batch(exe_path, addresses);
|
std::vector<SourceInfo> results = get_source_info_batch(exe_path, addresses);
|
||||||
|
|
||||||
|
// Filter out frames from assert.hpp
|
||||||
|
results.erase(std::remove_if(results.begin(), results.end(),
|
||||||
|
[](const SourceInfo& frame) {
|
||||||
|
if (frame.file.empty()) return false;
|
||||||
|
std::string_view file(frame.file);
|
||||||
|
return file.find("assert.hpp") != std::string_view::npos;
|
||||||
|
}),
|
||||||
|
results.end()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (results.empty()) {
|
||||||
|
std::cerr << " " << colors::red << "[no user frames available]" << colors::reset << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// First pass: find the maximum function name length for alignment
|
||||||
|
size_t max_func_length = 0;
|
||||||
|
for (const auto& frame : results) {
|
||||||
|
size_t length = frame.function.empty()
|
||||||
|
? strlen("[unknown function]")
|
||||||
|
: frame.function.length();
|
||||||
|
if (length > max_func_length) {
|
||||||
|
max_func_length = length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second pass: print with aligned output
|
||||||
for (size_t i = 0; i < results.size(); ++i) {
|
for (size_t i = 0; i < results.size(); ++i) {
|
||||||
const auto& frame = results[i];
|
const auto& frame = results[i];
|
||||||
std::cerr << " ";
|
std::cerr << " ";
|
||||||
|
|
||||||
|
// Print function name with alignment
|
||||||
|
size_t current_length;
|
||||||
if (!frame.function.empty()) {
|
if (!frame.function.empty()) {
|
||||||
std::cerr << colors::green << frame.function << colors::reset;
|
std::cerr << colors::green << frame.function << colors::reset;
|
||||||
|
current_length = frame.function.length();
|
||||||
} else {
|
} else {
|
||||||
std::cerr << colors::red << "[unknown function]" << colors::reset;
|
std::cerr << colors::red << "[unknown function]" << colors::reset;
|
||||||
|
current_length = strlen("[unknown function]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add padding to align the file/line text
|
||||||
if (!frame.file.empty() && frame.line > 0) {
|
if (!frame.file.empty() && frame.line > 0) {
|
||||||
std::cerr << " at " << colors::blue << frame.file << colors::reset
|
// Calculate padding (minimum 1 space)
|
||||||
|
size_t padding = (max_func_length > current_length)
|
||||||
|
? (max_func_length - current_length + 1)
|
||||||
|
: 1;
|
||||||
|
std::cerr << std::string(padding, ' ')
|
||||||
|
<< " " << colors::blue << frame.file << colors::reset
|
||||||
<< ":" << colors::magenta << frame.line << colors::reset;
|
<< ":" << colors::magenta << frame.line << colors::reset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
test.sh
4
test.sh
@@ -5,9 +5,9 @@ set -euo pipefail
|
|||||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
|
||||||
|
|
||||||
|
|
||||||
docker buildx build --load \
|
docker build \
|
||||||
-f "${SCRIPT_DIR}/Dockerfile.sos" \
|
-f "${SCRIPT_DIR}/Dockerfile.sos" \
|
||||||
-t gitea.jde.nz/public/simple-object-server:test \
|
-t simple-object-server:test \
|
||||||
"${SCRIPT_DIR}"
|
"${SCRIPT_DIR}"
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
services:
|
services:
|
||||||
sos:
|
sos:
|
||||||
image: gitea.jde.nz/public/simple-object-server:test
|
image: simple-object-server:test
|
||||||
container_name: sos-test
|
container_name: sos-test
|
||||||
network_mode: "host"
|
network_mode: "host"
|
||||||
ports:
|
ports:
|
||||||
|
Reference in New Issue
Block a user