name: Deploy # Define when the workflow should run on: # Allow manual triggering of the workflow from the Actions tab workflow_dispatch: # Allow inputs to be passed when manually triggering the workflow from the Actions tab inputs: DOCKERFILE_PATH: type: string description: 'Absolute path to the Dockerfile.' required: true default: 'dockerfiles/debian_mini' IMAGE_SIZE: type: string description: 'Image size, 950M max.' required: true default: '600M' LOGIN_UGID: type: string description: 'UID:GID of the starting process.' required: true default: "1000:1000" DEPLOY_TO_GITHUB_PAGES: type: boolean description: 'Deploy to Github pages.' required: true default: true GITHUB_RELEASE: type: boolean description: 'Upload GitHub release.' required: true default: false GITHUB_RELEASE_TAG: type: string description: 'Tag for the github release.' required: true default: "ext2_image" jobs: build: runs-on: ubuntu-latest # Image to run the worker on. env: TAG: "ext2-webvm-base-image" # Tag of docker image. IMAGE_SIZE: '${{ github.event.inputs.IMAGE_SIZE }}' DEPLOY_DIR: /webvm_deploy/ # Path to directory where we host the final image from. permissions: # Permissions to grant the GITHUB_TOKEN. contents: write # Required permission to make a github release. actions: 'write' # Required for the Dockerfile path guard clause. steps: # Checks-out our repository under $GITHUB_WORKSPACE, so our job can access it - uses: actions/checkout@v3 # Guard clause that cancels the workflow in case of an invalid DOCKERFILE_PATH. # The main reason for choosing this workaround for aborting the workflow is the fact that it does not display the workflow as successful, which can set false expectations. - name: DOCKERFILE_PATH guard clause shell: bash run: | if [ ! -f ${{ github.event.inputs.DOCKERFILE_PATH }} ]; then echo "::error title=Invalid Dockerfile path::No file found at ${{ github.event.inputs.DOCKERFILE_PATH }}" gh run cancel ${{ github.run_id }} gh run watch ${{ github.run_id }} fi env: GH_TOKEN: ${{ github.token }} # As required by the GitHub-CLI # Setting the IMAGE_NAME variable in GITHUB_ENV to __.ext2. - name: Generate the image_name. id: image_name_gen run: | echo "IMAGE_NAME=$(basename ${{ github.event.inputs.DOCKERFILE_PATH }})_$(date +%Y%m%d)_${{ github.run_id }}.ext2" >> $GITHUB_ENV # We extract the uid and gid from the uid:gid input. - run: | echo "LOGIN_UID=$(echo ${{ github.event.inputs.LOGIN_UGID }} | cut -d ':' -f1)" >> $GITHUB_ENV echo "LOGIN_GID=$(echo ${{ github.event.inputs.LOGIN_UGID }} | cut -d ':' -f2)" >> $GITHUB_ENV # Create directory to host the image from. - run: sudo mkdir -p $DEPLOY_DIR # Build the i386 Dockerfile image. - run: docker build . --tag $TAG --file ${{ github.event.inputs.DOCKERFILE_PATH }} --platform=i386 # Run the docker image so that we can export the container. # Run the Docker container with the Google Public DNS nameservers: 8.8.8.8, 8.8.4.4 - run: docker run --dns 8.8.8.8 --dns 8.8.4.4 -d $TAG # We create and mount the base ext2 image to extract the Docker container's filesystem its contents into. - name: Create ext2 image. run: | # Preallocate space for the ext2 image sudo fallocate -l $IMAGE_SIZE ${IMAGE_NAME} # Format to ext2 linux kernel revision 0 sudo mkfs.ext2 -r 0 ${IMAGE_NAME} # Mount the ext2 image to modify it sudo mount -o loop -t ext2 ${IMAGE_NAME} /mnt/ # We opt for 'docker cp --archive' over 'docker save' since our focus is solely on the end product rather than individual layers and metadata. # However, it's important to note that despite being specified in the documentation, the '--archive' flag does not currently preserve uid/gid information when copying files from the container to the host machine. # Another compelling reason to use 'docker cp' is that it preserves resolv.conf. - name: Export and unpack container filesystem contents into mounted ext2 image. run: | sudo docker cp -a $(sudo docker ps -aq):/ /mnt/ sudo umount /mnt/ # Result is an ext2 image for webvm. # Move required files for gh-pages deployment to the deployment directory $DEPLOY_DIR. - run: sudo mv assets examples xterm favicon.ico index.html login.html network.js scrollbar.css serviceWorker.js tower.ico $DEPLOY_DIR # The .txt suffix enabled HTTP compression for free - name: Generate image split chunks and .meta file run: | sudo split ${{ env.IMAGE_NAME }} ${{ env.DEPLOY_DIR }}/${{ env.IMAGE_NAME }}.c -a 6 -b 128k -x --additional-suffix=.txt sudo bash -c "stat -c%s ${{ env.IMAGE_NAME }} > ${{ env.DEPLOY_DIR }}/${{ env.IMAGE_NAME }}.meta" # This step updates the default index.html file by performing the following actions: # 1. Replaces all occurrences of UID and GID with their respective input parameters. # 2. Replaces all occurrences of IMAGE_URL with the URL to the image. # 3. Replaces all occurrences of DEVICE_TYPE to bytes. - name: Adjust index.html run: | sudo sed -i 's#UID#"${{ env.LOGIN_UID }}"#g' ${{ env.DEPLOY_DIR }}index.html sudo sed -i 's#GID#"${{ env.LOGIN_GID }}"#g' ${{ env.DEPLOY_DIR }}index.html sudo sed -i 's#IMAGE_URL#"${{ env.IMAGE_NAME }}"#g' ${{ env.DEPLOY_DIR }}index.html sudo sed -i 's#DEVICE_TYPE#"split"#g' ${{ env.DEPLOY_DIR }}index.html # We generate index.list files for our httpfs to function properly. - name: make index.list shell: bash run: | find $DEPLOY_DIR -type d | while read -r dir; do index_list="$dir/index.list"; sudo rm -f "$index_list"; sudo ls "$dir" | sudo tee "$index_list" > /dev/null; sudo chmod +rw "$index_list"; sudo echo "created $index_list"; done # Create a gh-pages artifact in order to deploy to gh-pages. - name: Upload GitHub Pages artifact uses: actions/upload-pages-artifact@v1.0.7 with: # Path of the directory containing the static assets for our gh pages deployment. path: ${{ env.DEPLOY_DIR }} # optional, default is _site/ - name: github release # To upload our final ext2 image as a github release. if: ${{ github.event.inputs.GITHUB_RELEASE == 'true' }} uses: softprops/action-gh-release@v0.1.15 with: target_commitish: ${{ github.sha }} # Last commit on the GITHUB_REF branch or tag tag_name: ${{ github.event.inputs.GITHUB_RELEASE_TAG }} # Tag of the release. fail_on_unmatched_files: 'true' # Fail in case of no matches with the file(s) glob(s). files: | # Assets to upload as release. ${{ env.IMAGE_NAME }} deploy_to_github_pages: # Job that deploys the github-pages artifact to github-pages. if: ${{ github.event.inputs.DEPLOY_TO_GITHUB_PAGES == 'true' }} needs: build environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} # Grant GITHUB_TOKEN the permissions required to make a Pages deployment permissions: pages: write # to deploy to Pages id-token: write # to verify the deployment originates from an appropriate source runs-on: ubuntu-latest steps: # Deployment to github pages - name: Deploy GitHub Pages site id: deployment uses: actions/deploy-pages@v2.0.0