From 14d5822193abd10f805b09bf65b086625e605ae8 Mon Sep 17 00:00:00 2001 From: Domingo Dirutigliano Date: Mon, 4 Aug 2025 08:33:15 +0200 Subject: [PATCH] gh action to upload rootfs on gh release + downloading rootfs from there --- .github/workflows/docker-rootfs-asset.yml | 87 ++++++++++++++++++++++ start.py | 88 +++++++++++++++++------ 2 files changed, 154 insertions(+), 21 deletions(-) create mode 100644 .github/workflows/docker-rootfs-asset.yml diff --git a/.github/workflows/docker-rootfs-asset.yml b/.github/workflows/docker-rootfs-asset.yml new file mode 100644 index 0000000..dedcb80 --- /dev/null +++ b/.github/workflows/docker-rootfs-asset.yml @@ -0,0 +1,87 @@ +name: Create Docker rootfs assets + +on: + workflow_run: + workflows: ["Create and publish a Docker image"] + types: + - completed + branches: + - main + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + create-rootfs-assets: + runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'success' }} + permissions: + contents: write + packages: read + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@master + with: + platforms: all + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@master + + - name: Log in to the Container registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Get latest release tag + id: get_tag + run: | + LATEST_TAG=$(curl -s https://api.github.com/repos/${{ github.repository }}/releases/latest | jq -r '.tag_name') + echo "tag=$LATEST_TAG" >> $GITHUB_OUTPUT + echo "Latest release tag: $LATEST_TAG" + + - name: Export rootfs for amd64 + run: | + echo "Creating and exporting amd64 container..." + CONTAINER_ID=$(docker create --platform linux/amd64 ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.get_tag.outputs.tag }}) + docker export $CONTAINER_ID --output="firegex-rootfs-amd64.tar" + docker rm $CONTAINER_ID + echo "Compressing amd64 rootfs..." + gzip firegex-rootfs-amd64.tar + ls -lh firegex-rootfs-amd64.tar.gz + + - name: Export rootfs for arm64 + run: | + echo "Creating and exporting arm64 container..." + CONTAINER_ID=$(docker create --platform linux/arm64 ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.get_tag.outputs.tag }}) + docker export $CONTAINER_ID --output="firegex-rootfs-arm64.tar" + docker rm $CONTAINER_ID + echo "Compressing arm64 rootfs..." + gzip firegex-rootfs-arm64.tar + ls -lh firegex-rootfs-arm64.tar.gz + + - name: Calculate checksums + run: | + echo "Calculating checksums..." + sha256sum firegex-rootfs-amd64.tar.gz > firegex-rootfs-amd64.tar.gz.sha256 + sha256sum firegex-rootfs-arm64.tar.gz > firegex-rootfs-arm64.tar.gz.sha256 + cat *.sha256 + + - name: Upload rootfs assets to release + run: | + echo "Uploading assets to release ${{ steps.get_tag.outputs.tag }}..." + gh release upload ${{ steps.get_tag.outputs.tag }} \ + firegex-rootfs-amd64.tar.gz \ + firegex-rootfs-amd64.tar.gz.sha256 \ + firegex-rootfs-arm64.tar.gz \ + firegex-rootfs-arm64.tar.gz.sha256 \ + --clobber + echo "Assets uploaded successfully!" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/start.py b/start.py index d050493..f4de128 100755 --- a/start.py +++ b/start.py @@ -508,6 +508,44 @@ def cleanup_standalone_mounts(): # Run all umount commands in one batch run_privileged_commands(umount_commands, "cleanup mounts") +def get_latest_release_tag(): + """Get the latest release tag from GitHub API""" + import urllib.request + import json + + try: + url = "https://api.github.com/repos/Pwnzer0tt1/firegex/releases/latest" + with urllib.request.urlopen(url) as response: + data = json.loads(response.read().decode()) + return data.get('tag_name') + except Exception as e: + puts(f"Failed to get latest release tag: {e}", color=colors.red) + return None + +def get_architecture(): + """Get current architecture (amd64 or arm64)""" + import platform + arch = platform.machine().lower() + if arch in ['x86_64', 'amd64']: + return 'amd64' + elif arch in ['aarch64', 'arm64']: + return 'arm64' + else: + puts(f"Unsupported architecture: {arch}", color=colors.red) + return None + +def download_file(url, filename): + """Download a file using urllib""" + import urllib.request + + try: + puts(f"Downloading {filename}...", color=colors.green) + urllib.request.urlretrieve(url, filename) + return True + except Exception as e: + puts(f"Failed to download {filename}: {e}", color=colors.red) + return False + def setup_standalone_rootfs(): """Set up the standalone rootfs""" puts("Setting up standalone mode...", color=colors.green) @@ -526,31 +564,36 @@ def setup_standalone_rootfs(): puts(f"Failed to create rootfs directory: {e}", color=colors.red) return False - # Create temporary container and export it - puts("Downloading and extracting Docker image...", color=colors.green) - - # Create container from image - create_cmd = f"docker create ghcr.io/pwnzer0tt1/firegex:{args.version}" - result = subprocess.run(create_cmd, shell=True, capture_output=True, text=True) - if result.returncode != 0: - puts(f"Failed to create container: {result.stderr}", color=colors.red) + # Get latest release tag + release_tag = get_latest_release_tag() + if not release_tag: + puts("Failed to get latest release tag", color=colors.red) return False - container_id = result.stdout.strip() + # Get current architecture + arch = get_architecture() + if not arch: + return False + + # Download rootfs from GitHub releases + puts(f"Downloading rootfs for {arch} architecture from GitHub releases...", color=colors.green) + + # Construct download URL + rootfs_filename = f"firegex-rootfs-{arch}.tar.gz" + download_url = f"https://github.com/Pwnzer0tt1/firegex/releases/download/{release_tag}/{rootfs_filename}" + tar_path = os.path.join(g.rootfs_path, rootfs_filename) + + # Download the rootfs archive + if not download_file(download_url, tar_path): + return False try: - # Export container to tar file - tar_path = os.path.join(g.rootfs_path, "latest.tar") - export_cmd = f"docker export --output={tar_path} {container_id}" - if not safe_run_command(export_cmd): - return False - - # Extract tar file + # Extract tar.gz file puts("Extracting rootfs...", color=colors.green) - with tarfile.open(tar_path, 'r') as tar: + with tarfile.open(tar_path, 'r:gz') as tar: tar.extractall(path=g.rootfs_path, filter=lambda _: False) - # Remove tar file + # Remove tar.gz file os.remove(tar_path) # Create necessary directories @@ -561,9 +604,12 @@ def setup_standalone_rootfs(): puts("Rootfs setup completed", color=colors.green) return True - finally: - # Clean up container - safe_run_command(f"docker rm {container_id}", check_result=False) + except Exception as e: + puts(f"Failed to extract rootfs: {e}", color=colors.red) + # Clean up partial extraction + if os.path.exists(tar_path): + os.remove(tar_path) + return False def setup_standalone_mounts(): """Set up bind mounts for standalone mode"""