diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..d68e65a --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,107 @@ +name: CI/CD Pipeline + +on: + push: + branches: + - develop + tags: + - 'v*' + pull_request: + types: [opened, synchronize, reopened] + +env: + REGISTRY: labs.phundrak.com + IMAGE_NAME: phundrak/roll-one-ring + +jobs: + build-and-publish: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Install Nix + uses: cachix/install-nix-action@v31.6.0 + with: + github_access_token: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup Cachix + uses: cachix/cachix-action@v16 + with: + name: roll-one-ring + authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' + skipPush: ${{ github.event_name == 'pull_request' }} + + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Get version from Cargo.toml + id: get-version + run: | + nix run .#version + VERSION=$(nix run .#version 2>/dev/null || echo "unknown") + echo $VERSION + echo "version=$VERSION" >> $GITHUB_OUTPUT + + - name: Determine tags + id: determine-tags + run: | + TAGS="" + + if [[ "${{ github.event_name }}" == "push" ]]; then + if [[ "${{ github.ref }}" == "refs/heads/develop" ]]; then + # Push to develop branch + TAGS="${{ env.IMAGE_NAME }}:develop" + elif [[ "${{ github.ref }}" == refs/tags/* ]]; then + # Tag push + VERSION_TAG=${GITHUB_REF#refs/tags/} + # Remove 'v' prefix if present + VERSION_TAG=${VERSION_TAG#v} + TAGS="${{ env.IMAGE_NAME }}:latest,${{ env.IMAGE_NAME }}:${VERSION_TAG}" + fi + elif [[ "${{ github.event_name }}" == "pull_request" ]]; then + # Pull request + PR_NUMBER=${{ github.event.number }} + TAGS="${{ env.IMAGE_NAME }}:pr${PR_NUMBER}" + fi + + echo "tags=$TAGS" >> $GITHUB_OUTPUT + echo "Tags to build: $TAGS" + + - name: Build Docker image with Nix + run: | + echo "Building Docker image..." + nix build .#docker + + # Load the image into Docker + docker load < result + + # Get the image ID that was just loaded + IMAGE_ID=$(docker images --format "table {{.Repository}}:{{.Tag}}\t{{.ID}}" | grep "${{ env.IMAGE_NAME }}:latest" | awk '{print $2}' | head -1) + echo "Loaded image ID: $IMAGE_ID" + echo "image_id=$IMAGE_ID" >> $GITHUB_ENV + + - name: Tag and push Docker image + run: | + TAGS="${{ steps.determine-tags.outputs.tags }}" + + if [ -n "$TAGS" ]; then + IFS=',' read -ra TAG_ARRAY <<< "$TAGS" + for tag in "${TAG_ARRAY[@]}"; do + echo "Tagging and pushing: $tag" + docker tag ${{ env.image_id }} "$tag" + docker push "$tag" + done + fi + + - name: Output image tags + run: | + echo "Built and pushed the following tags:" + echo "${{ steps.determine-tags.outputs.tags }}" diff --git a/flake.nix b/flake.nix index 8abbbe8..01a0ca5 100644 --- a/flake.nix +++ b/flake.nix @@ -17,28 +17,45 @@ cargo = rustVersion; rustc = rustVersion; }; + appName = "roll-one-ring"; + cargoToml = builtins.fromTOML (builtins.readFile ./Cargo.toml); + version = cargoToml.package.version; appRustBuild = rustPlatform.buildRustPackage { pname = appName; - version = "0.1.0"; + version = version; src = ./.; cargoLock.lockFile = ./Cargo.lock; }; - dockerImage = pkgs.dockerTools.buildLayeredImage { - name = appName; + + makeDockerImage = tag: pkgs.dockerTools.buildLayeredImage { + name = "phundrak/${appName}"; + inherit tag; config = { Entrypoint = ["${appRustBuild}/bin/${appName}"]; Env = [ "SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt" ]; - Tag = "latest"; }; contents = [appRustBuild pkgs.cacert]; }; + + dockerImageLatest = makeDockerImage "latest"; + dockerImageVersioned = makeDockerImage version; + in { packages = { rustPackage = appRustBuild; - docker = dockerImage; + docker = dockerImageLatest; + docker-versioned = dockerImageVersioned; + }; + defaultPackage = dockerImageLatest; + apps = { + version = { + type = "app"; + program = "${pkgs.writeShellScript "version" '' + echo "${version}" + ''}"; + }; }; - defaultPackage = dockerImage; devShell = with pkgs; mkShell { buildInputs = [ bacon