From 90be06c66b8ba8269384c0d41b7bdf9608fe3c92 Mon Sep 17 00:00:00 2001 From: John <16479678+john-cd@users.noreply.github.com> Date: Mon, 12 Feb 2024 05:20:02 +0000 Subject: [PATCH] Publish to crates.io --- .devcontainer/Dockerfile | 30 +++++++++--------- .devcontainer/ci.sh | 2 +- .devcontainer/compose-ci.yaml | 9 ++++++ .devcontainer/publish.sh | 58 +++++++++++++++++++++++++++++++++++ .github/workflows/publish.yml | 25 --------------- 5 files changed, 84 insertions(+), 40 deletions(-) create mode 100755 .devcontainer/publish.sh delete mode 100644 .github/workflows/publish.yml diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index da0e4ae..afaec57 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -11,18 +11,16 @@ FROM rust:${RUST_IMAGE_LABEL} as base SHELL ["bash", "-c"] -## Install linker and other utilities -# RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ -# --mount=type=cache,target=/var/lib/apt,sharing=locked \ -# apt-get update \ -# && export DEBIAN_FRONTEND=noninteractive \ -# && apt-get install -y --no-install-recommends mold clang \ -# && apt-get autoremove -y \ -# && apt-get clean -y \ -# && rm -rf /var/lib/apt/lists/* -## Alternatively, use `lld` instead of the `mold` linker -## Configuration in .cargo/config.toml -## If using the `slim` Rust image, you may need to install: curl pkg-config libssl-dev +## Install utilities +RUN apt-get update \ + && export DEBIAN_FRONTEND=noninteractive \ + && apt-get install -y --no-install-recommends jq \ + && apt-get autoremove -y \ + && apt-get clean -y \ + && rm -rf /var/lib/apt/lists/* +## To cache: +## --mount=type=cache,target=/var/cache/apt,sharing=locked \ +## --mount=type=cache,target=/var/lib/apt,sharing=locked \ ## Update Rust if needed (note: `rustup update stable && rustup default stable` is required for Rust 1.74 -> Rust 1.75 somehow) RUN rustup update @@ -83,7 +81,7 @@ ENTRYPOINT [ "./.devcontainer/dev.sh" ] CMD [ "sleep", "infinity" ] ## -------------------------------- -## Stage for Continuous Integration +## Stage for Continuous Integration / Deployment FROM base as ci ## Copy the code in the container (in WORKDIR), excluding what is in .dockerignore @@ -92,6 +90,10 @@ COPY . . ENV CARGO_TARGET_DIR=./target/ ## Make sure the start scripts have permission to execute -RUN chmod +x ./.devcontainer/ci.sh +RUN chmod +x ./.devcontainer/ci.sh ./.devcontainer/publish.sh +## `ci.sh` builds / tests the code and builds / tests the user guide. +## The user guide HTML that has been built is exported +## via the bind mount in `compose-ci.yaml` back to the CI host, +## so that it could be deployed to GitHub Pages. ENTRYPOINT [ "./.devcontainer/ci.sh" ] diff --git a/.devcontainer/ci.sh b/.devcontainer/ci.sh index 901915f..c5bf250 100755 --- a/.devcontainer/ci.sh +++ b/.devcontainer/ci.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#! /usr/bin/env bash set -eux set -o pipefail diff --git a/.devcontainer/compose-ci.yaml b/.devcontainer/compose-ci.yaml index 4310bd2..cb4ee25 100644 --- a/.devcontainer/compose-ci.yaml +++ b/.devcontainer/compose-ci.yaml @@ -18,3 +18,12 @@ services: target: /code/userguide/book/ bind: create_host_path: true + secrets: + - crates_token + +## crates_token secret is created as _crates_token when the application is deployed, +## by registering the content of the CRATES_TOKEN environment variable as a platform secret. +## https://docs.docker.com/compose/compose-file/09-secrets/ +secrets: + crates_token: + environment: "CRATES_TOKEN" diff --git a/.devcontainer/publish.sh b/.devcontainer/publish.sh new file mode 100755 index 0000000..9e004d4 --- /dev/null +++ b/.devcontainer/publish.sh @@ -0,0 +1,58 @@ +#! /usr/bin/env bash +set -eu +set -o pipefail + +echo "This script packages and publishes the crate to https://crates.io/" +echo "It is meant to run AFTER ci.sh" + +# https://pubs.opengroup.org/onlinepubs/9699919799/utilities/getopts.html +yflag= +while getopts y name +do + case $name in + y) yflag=1;; + ?) printf "Usage: %s -y\nThe -y option is REQUIRED to confirm publication.\n" $0 + exit 2;; + esac +done +shift $(($OPTIND - 1)) + +## -z tests if the string has zero length +if [ -z "$yflag" ]; then + echo "You MUST pass the -y option to confirm that you truly want to PUBLISH." + exit 1 +fi + +## if the CRATES_TOKEN env var is defined, build, then package and publish +if [ ! -v CRATES_TOKEN ]; then + echo "The env. variable CRATES_TOKEN is not set." + exit 3 +fi + +echo "----------" +CARGO_TOML_VERSION=$(cargo metadata --no-deps --locked --format-version 1 | jq '.packages | .[0] | .version') +echo "Version in Cargo.toml: ${CARGO_TOML_VERSION}" + +CRATES_IO_VERSION=$(cargo search mdbook-utils | sed -E 's/^.*"(.*)".*$/\1/') +echo "Version in crates.io: ${CRATES_IO_VERSION}" + +# GIT_TAG=$(git describe --tags $(git rev-list --tags --max-count=1)) +# echo "Git tag: ${GIT_TAG}" + +## TODO check that the last commit has been tagged, that the tag corresponds to the version in Cargo.toml, +## and that the version number is larger than the one in crates.io. +# https://stackoverflow.com/questions/1474115/how-to-find-the-tag-associated-with-a-given-git-commit +# https://stackoverflow.com/questions/1404796/how-can-i-get-the-latest-tag-name-in-current-branch-in-git +# git log --pretty=oneline +# git tag +# git describe --exact-match + +echo "----------" +echo "Files that will be packaged:" +cargo package --locked --list # Print files included in a package. + +echo "----------" +echo "Package & publish:" +cargo publish --dry-run --locked --token ${CRATES_TOKEN} + +echo "----------" diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index 5de3608..0000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,25 +0,0 @@ -on: - #push: - # Pattern matched against refs/tags - #tags: - # - '*' # Push events to every tag not containing / - workflow_dispatch: - -name: Publish - -jobs: - publish: - name: Publish to crates.io - runs-on: ubuntu-latest - steps: - - name: Basic information - run: echo "The job was automatically triggered by a ${{ github.event_name }} event from @${{ github.actor }}. The OS is ${{ runner.os }}" - - name: Checkout sources - uses: actions/checkout@v4 - - name: Build docker image - run: docker compose -f .devcontainer/compose.yaml -f .devcontainer/compose-ci.yaml build - - name: Build the code - run: docker compose -f .devcontainer/compose.yaml -f .devcontainer/compose-ci.yaml run mdbook-utils - # - run: cargo publish --token ${CRATES_TOKEN} - # env: - # CRATES_TOKEN: ${{ secrets.CRATES_TOKEN }}