name: Deploy Site description: Deploy static site via S3 and Nomad dispatch inputs: site-name: description: 'Site identifier (used as service name in Nomad)' required: true traefik-rule: description: 'Traefik routing rule (e.g., Host(`example.com`) or Host(`example.com`) || Host(`www.example.com`))' required: true source-dir: description: 'Directory containing built site' required: false default: '.' s3-endpoint: description: 'S3 endpoint' required: false default: 'https://s3.toph.so' runs: using: composite steps: - name: Install AWS CLI and Nomad shell: bash run: | # Install AWS CLI if not present if ! command -v aws &> /dev/null; then curl -sL "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "/tmp/awscliv2.zip" unzip -q /tmp/awscliv2.zip -d /tmp sudo /tmp/aws/install fi # Install Nomad if not present if ! command -v nomad &> /dev/null; then NOMAD_VERSION="1.8.4" curl -sL "https://releases.hashicorp.com/nomad/${NOMAD_VERSION}/nomad_${NOMAD_VERSION}_linux_amd64.zip" -o "/tmp/nomad.zip" unzip -q /tmp/nomad.zip -d /tmp sudo mv /tmp/nomad /usr/local/bin/ sudo chmod +x /usr/local/bin/nomad fi # Set Nomad address echo "NOMAD_ADDR=http://alvin:4646" >> $GITHUB_ENV - name: Package and upload to S3 shell: bash run: | cd "${{ inputs.source-dir }}" ARTIFACT_NAME="${{ github.sha }}.tar.gz" tar czf "/tmp/${ARTIFACT_NAME}" . # Configure AWS CLI for S3 export AWS_ACCESS_KEY_ID="${{ env.S3_ACCESS_KEY }}" export AWS_SECRET_ACCESS_KEY="${{ env.S3_SECRET_KEY }}" export AWS_ENDPOINT_URL="${{ inputs.s3-endpoint }}" export AWS_EC2_METADATA_DISABLED=true # Upload to S3 aws s3 cp "/tmp/${ARTIFACT_NAME}" "s3://artifacts/${ARTIFACT_NAME}" # Make publicly readable aws s3api put-object-acl \ --bucket artifacts \ --key "${ARTIFACT_NAME}" \ --acl public-read echo "📦 Artifact uploaded: ${{ inputs.s3-endpoint }}/artifacts/${ARTIFACT_NAME}" - name: Deploy via Nomad shell: bash run: | cat > /tmp/deploy-${{ inputs.site-name }}.nomad.json <<'NOMAD_EOF' { "Job": { "ID": "${{ inputs.site-name }}", "Name": "${{ inputs.site-name }}", "Namespace": "static-sites", "Type": "service", "Datacenters": ["contabo"], "Constraints": [{ "LTarget": "${node.unique.name}", "RTarget": "alvin", "Operand": "=" }], "TaskGroups": [{ "Name": "web", "Count": 1, "Networks": [{ "Mode": "bridge", "DynamicPorts": [{ "Label": "http", "To": 8080 }] }], "Services": [{ "Name": "${{ inputs.site-name }}", "PortLabel": "http", "Provider": "nomad", "Tags": [ "traefik.enable=true", "traefik.http.routers.${{ inputs.site-name }}.rule=${{ inputs.traefik-rule }}", "traefik.http.routers.${{ inputs.site-name }}.entrypoints=websecure", "traefik.http.routers.${{ inputs.site-name }}.tls.certresolver=letsencrypt" ] }], "Tasks": [{ "Name": "server", "Driver": "docker", "Config": { "image": "joseluisq/static-web-server:2", "ports": ["http"] }, "Env": { "SERVER_ROOT": "/local/public", "SERVER_LOG_LEVEL": "info" }, "Artifacts": [{ "GetterSource": "${{ inputs.s3-endpoint }}/artifacts/${{ github.sha }}.tar.gz", "RelativeDest": "local/public", "GetterMode": "dir" }], "Resources": { "CPU": 100, "MemoryMB": 64 } }] }] } } NOMAD_EOF nomad job run /tmp/deploy-${{ inputs.site-name }}.nomad.json - name: Deployment summary shell: bash run: | echo "✅ Deployed ${{ inputs.site-name }}" echo "📋 Traefik rule: ${{ inputs.traefik-rule }}"