diff --git a/.forgejo/workflows/build.yaml b/.forgejo/workflows/build.yaml new file mode 100644 index 0000000..c8a8b85 --- /dev/null +++ b/.forgejo/workflows/build.yaml @@ -0,0 +1,45 @@ +name: Build & Upload tux-dock + +on: + push: + branches: + - main + - dev + +jobs: + build: + runs-on: [self-hosted] + env: + BRANCH: ${{ github.ref_name }} + COMMIT: ${{ github.sha }} + steps: + - name: Clone current branch + run: | + git clone --branch "$BRANCH" https://mentalnet.xyz/forgejo/markmental/tuxdock.git . + echo "โœ… Checked out branch $BRANCH ($COMMIT)" + + - name: Compile tux-dock + run: | + g++ -std=c++17 main.cpp -o tux-dock + chmod +x tux-dock + echo "๐ŸŽ‰ tux-dock compiled and marked executable!" + + - name: Verify build + run: file tux-dock + + - name: Prepare build artifact (tar.gz) + run: | + mkdir -p build/"$BRANCH" + mv tux-dock build/"$BRANCH"/ + SHORT_HASH=$(echo "$COMMIT" | cut -c1-7) + TAR_NAME="tux-dock-linux-x86_64-${BRANCH}-${SHORT_HASH}.tar.gz" + tar czf "$TAR_NAME" -C build "$BRANCH" + echo "๐Ÿ“ฆ Created $TAR_NAME" + + - name: Upload build artifact + uses: actions/upload-artifact@v3 + with: + name: tux-dock-linux-x86_64-${{ env.BRANCH }}-${{ env.COMMIT }} + path: tux-dock-linux-x86_64-${{ env.BRANCH }}-*.tar.gz + + diff --git a/README.md b/README.md index 04475bf..f790cbe 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ It offers a clean, interactive menu for common Docker operations like pulling im - ๐Ÿ”น **Script-to-image workflow** โ€” turn a bash setup script into a Dockerfile and build the resulting image in one go. - ๐Ÿ”น **Quick MySQL setup** โ€” spin up a MySQL container with version, password, and port configuration in seconds. - ๐Ÿ”น **Get container IP address** โ€” cleanly retrieves and displays only the containerโ€™s assigned IP. +- ๐Ÿ”น **Run detached commands** โ€” execute background jobs inside a container without attaching an interactive shell. - ๐Ÿ”น **Modern C++ design** โ€” built with classes, minimal dependencies, and clear abstractions. --- @@ -58,10 +59,11 @@ Tux-Dock: Docker Management Menu 8. Stop Container 9. Remove Container 10. Attach Shell to Running Container -11. Spin Up MySQL Container -12. Get Container IP Address -13. Create Dockerfile & Build Image from Bash Script -14. Exit +11. Run Detached Command in Container +12. Spin Up MySQL Container +13. Get Container IP Address +14. Create Dockerfile & Build Image from Bash Script +15. Exit ``` Each action guides you through the required steps. @@ -92,6 +94,7 @@ class DockerManager { void runContainerInteractive(); void listContainers() const; void startInteractive(); + void execDetachedCommand(); void stopContainer(); void showContainerIP(); }; diff --git a/main.cpp b/main.cpp index 16b6fe9..e5b0c29 100644 --- a/main.cpp +++ b/main.cpp @@ -6,6 +6,7 @@ #include #include #include +#include using namespace std; @@ -21,6 +22,7 @@ public: void stopContainer(); void removeContainer(); void execShell(); + void execDetachedCommand(); void createDockerfile(); void spinUpMySQL(); void showContainerIP(); @@ -153,6 +155,35 @@ void DockerManager::execShell() { if (!id.empty()) runCommand("docker exec -it " + id + " /bin/sh"); } +void DockerManager::execDetachedCommand() { + string id = selectContainer("Select container to run command in (detached)"); + if (id.empty()) return; + + // Flush any leftover newline before using getline + cin.ignore(numeric_limits::max(), '\n'); + + string command; + cout << "Enter command to execute inside the container: "; + getline(cin, command); + + if (command.empty()) { + cout << "No command entered. Aborting.\n"; + return; + } + + string escapedCommand; + escapedCommand.reserve(command.size() * 2); + for (char c : command) { + if (c == '"' || c == '\\') + escapedCommand += '\\'; + escapedCommand += c; + } + + cout << "Executing command in detached mode...\n"; + runCommand("docker exec -d " + id + " /bin/sh -c \"" + escapedCommand + "\""); + cout << "Command dispatched.\n"; +} + void DockerManager::spinUpMySQL() { string port, password, version; cout << "Enter port mapping (e.g., 3306:3306): "; @@ -275,10 +306,11 @@ int main() { << "8. Stop Container\n" << "9. Remove Container\n" << "10. Attach Shell to Running Container\n" - << "11. Spin Up MySQL Container\n" - << "12. Get Container IP Address\n" - << "13. Create Dockerfile & Build Image from Bash Script\n" - << "14. Exit\n" + << "11. Run Detached Command in Container\n" + << "12. Spin Up MySQL Container\n" + << "13. Get Container IP Address\n" + << "14. Create Dockerfile & Build Image from Bash Script\n" + << "15. Exit\n" << "----------------------------------\n" << "Choose an option: "; @@ -295,10 +327,11 @@ int main() { case 8: docker.stopContainer(); break; case 9: docker.removeContainer(); break; case 10: docker.execShell(); break; - case 11: docker.spinUpMySQL(); break; - case 12: docker.showContainerIP(); break; - case 13: docker.createDockerfile(); break; - case 14: + case 11: docker.execDetachedCommand(); break; + case 12: docker.spinUpMySQL(); break; + case 13: docker.showContainerIP(); break; + case 14: docker.createDockerfile(); break; + case 15: cout << "Exiting Tux-Dock.\n"; return 0; default: diff --git a/tux-dock b/tux-dock deleted file mode 100755 index 5312b2c..0000000 Binary files a/tux-dock and /dev/null differ