docs: add TeamPCP/CanisterWorm supply chain assessment to SECURITY.md #85
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: docker-publish | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| publish_latest: | |
| description: 'Also publish the latest tag' | |
| default: 'true' | |
| required: true | |
| type: choice | |
| options: | |
| - 'true' | |
| - 'false' | |
| release_tag: | |
| description: 'Tag to build (e.g. webssh2-server-v2.3.5); leave blank to use the selected ref' | |
| default: '' | |
| required: false | |
| type: string | |
| release: | |
| types: | |
| - published | |
| push: | |
| branches: | |
| - main | |
| concurrency: | |
| group: docker-publish-${{ github.event_name }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| build-and-push: | |
| runs-on: ubuntu-latest | |
| # Skip push events if this commit has a release tag (release event will handle it) | |
| if: | | |
| github.event_name != 'push' || | |
| !startsWith(github.event.head_commit.message, 'chore(main): release webssh2-server') | |
| permissions: | |
| contents: write | |
| packages: write | |
| env: | |
| DOCKERHUB_USER: ${{ secrets.DOCKER_USERNAME }} | |
| DOCKERHUB_TOKEN: ${{ secrets.DOCKER_TOKEN }} | |
| steps: | |
| - name: Check required secrets | |
| if: ${{ env.DOCKERHUB_USER == '' || env.DOCKERHUB_TOKEN == '' }} | |
| run: | | |
| echo '::error::DOCKERHUB_USERNAME and DOCKERHUB_TOKEN secrets are required' >&2 | |
| exit 1 | |
| - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
| with: | |
| fetch-depth: 0 | |
| fetch-tags: true | |
| ref: ${{ inputs.release_tag != '' && inputs.release_tag || github.ref }} | |
| - uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 | |
| with: | |
| platforms: linux/amd64,linux/arm64 | |
| - uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 | |
| - uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 | |
| with: | |
| registry: docker.io | |
| username: ${{ env.DOCKERHUB_USER }} | |
| password: ${{ env.DOCKERHUB_TOKEN }} | |
| - name: Login to GitHub Container Registry | |
| uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Normalize git ref context | |
| run: | | |
| ref="${GITHUB_REF:-}" | |
| ref_name="${GITHUB_REF_NAME:-}" | |
| release_tag="${RELEASE_TAG_NAME:-}" | |
| # First, check if a release tag was explicitly provided (via event or workflow input) | |
| if [ -n "$release_tag" ]; then | |
| ref="refs/tags/$release_tag" | |
| ref_name="$release_tag" | |
| elif [ -z "$ref" ] && [ -n "$ref_name" ]; then | |
| ref="refs/tags/$ref_name" | |
| fi | |
| # If we're on a push event (not an explicit release or tag), check if current commit has a release tag | |
| # This handles the case where release-please creates a release AND pushes to main | |
| if [ "$GITHUB_EVENT_NAME" = "push" ] && [[ "$ref_name" != webssh2-server-v* ]]; then | |
| echo "Push event detected, checking for release tag on current commit..." | |
| tag_at_head=$(git describe --tags --exact-match HEAD 2>/dev/null || echo "") | |
| if [[ "$tag_at_head" =~ ^webssh2-server-v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | |
| echo "Found release tag at HEAD: $tag_at_head" | |
| ref="refs/tags/$tag_at_head" | |
| ref_name="$tag_at_head" | |
| fi | |
| fi | |
| echo "EFFECTIVE_REF=$ref" >> "$GITHUB_ENV" | |
| echo "EFFECTIVE_REF_NAME=$ref_name" >> "$GITHUB_ENV" | |
| echo "Effective ref: $ref" | |
| echo "Effective ref_name: $ref_name" | |
| env: | |
| RELEASE_TAG_NAME: ${{ github.event.release.tag_name || inputs.release_tag || '' }} | |
| - name: Derive release semver tags | |
| id: release_meta | |
| run: | | |
| ref_name="${EFFECTIVE_REF_NAME:-}" | |
| prefix='webssh2-server-v' | |
| if [[ "$ref_name" =~ ^${prefix}([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then | |
| major="${BASH_REMATCH[1]}" | |
| minor="${BASH_REMATCH[2]}" | |
| patch="${BASH_REMATCH[3]}" | |
| echo "has_release=true" >> "$GITHUB_OUTPUT" | |
| echo "semver_full=${major}.${minor}.${patch}" >> "$GITHUB_OUTPUT" | |
| echo "semver_minor=${major}.${minor}" >> "$GITHUB_OUTPUT" | |
| echo "semver_major=${major}" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "has_release=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Derive GHCR image name | |
| id: ghcr | |
| run: | | |
| owner=$(echo "${GITHUB_REPOSITORY_OWNER}" | tr '[:upper:]' '[:lower:]') | |
| echo "image=ghcr.io/${owner}/webssh2" >> "${GITHUB_OUTPUT}" | |
| - id: meta | |
| uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 | |
| with: | |
| images: | | |
| docker.io/billchurch/webssh2 | |
| ${{ steps.ghcr.outputs.image }} | |
| tags: | | |
| type=raw,value=latest,enable=${{ github.event_name == 'release' && github.event.action == 'published' }} | |
| type=raw,value=latest,enable=${{ github.event_name == 'workflow_dispatch' && github.event.inputs.publish_latest == 'true' }} | |
| type=raw,value=main,enable=${{ (github.event_name == 'push' && github.ref == 'refs/heads/main') || (github.event_name == 'release' && github.event.action == 'published') }} | |
| type=raw,value=${{ steps.release_meta.outputs.semver_full }},enable=${{ steps.release_meta.outputs.has_release == 'true' }} | |
| type=raw,value=${{ steps.release_meta.outputs.semver_minor }},enable=${{ steps.release_meta.outputs.has_release == 'true' }} | |
| type=raw,value=${{ steps.release_meta.outputs.semver_major }},enable=${{ steps.release_meta.outputs.has_release == 'true' }} | |
| type=ref,event=branch,enable=${{ (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && github.ref != 'refs/heads/main' }} | |
| type=sha | |
| - name: Build and push docker image | |
| id: build | |
| uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 | |
| timeout-minutes: 60 | |
| with: | |
| context: . | |
| file: ./Dockerfile | |
| push: true | |
| platforms: linux/amd64,linux/arm64 | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| # BuildKit cache configuration | |
| # - Use GitHub Actions cache for faster rebuilds | |
| # - mode=max caches all layers (not just final stage) | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| # BuildKit features for optimization | |
| build-args: | | |
| BUILDKIT_INLINE_CACHE=1 | |
| - name: Test docker image | |
| run: | | |
| # Pull the image we just built (for current platform) | |
| docker pull ${{ steps.ghcr.outputs.image }}:sha-${GITHUB_SHA::7} | |
| # Start container and verify it runs | |
| CONTAINER_ID=$(docker run -d --rm \ | |
| -e DEBUG=webssh2:* \ | |
| ${{ steps.ghcr.outputs.image }}:sha-${GITHUB_SHA::7}) | |
| # Wait up to 30 seconds for startup | |
| for i in {1..30}; do | |
| if docker logs "$CONTAINER_ID" 2>&1 | grep -q "server started successfully"; then | |
| echo "✓ Container started successfully" | |
| docker stop "$CONTAINER_ID" | |
| exit 0 | |
| fi | |
| sleep 1 | |
| done | |
| echo "✗ Container failed to start" | |
| docker logs "$CONTAINER_ID" | |
| docker stop "$CONTAINER_ID" | |
| exit 1 | |
| - name: Update release notes with Docker images | |
| if: ${{ steps.release_meta.outputs.has_release == 'true' }} | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| RELEASE_TAG: ${{ env.EFFECTIVE_REF_NAME }} | |
| SEMVER_FULL: ${{ steps.release_meta.outputs.semver_full }} | |
| IMAGE_DIGEST: ${{ steps.build.outputs.digest }} | |
| run: | | |
| # Get current release body | |
| CURRENT_BODY=$(gh release view "$RELEASE_TAG" --json body --jq '.body') | |
| # Create Docker images section | |
| DOCKER_SECTION=" | |
| ## 🐳 Docker Images | |
| This release is available as multi-platform Docker images (linux/amd64, linux/arm64): | |
| ### Docker Hub | |
| \`\`\`bash | |
| docker pull billchurch/webssh2:latest | |
| docker pull billchurch/webssh2:${SEMVER_FULL} | |
| docker pull billchurch/webssh2:${{ steps.release_meta.outputs.semver_minor }} | |
| docker pull billchurch/webssh2:${{ steps.release_meta.outputs.semver_major }} | |
| \`\`\` | |
| ### GitHub Container Registry | |
| \`\`\`bash | |
| docker pull ghcr.io/billchurch/webssh2:latest | |
| docker pull ghcr.io/billchurch/webssh2:${SEMVER_FULL} | |
| docker pull ghcr.io/billchurch/webssh2:${{ steps.release_meta.outputs.semver_minor }} | |
| docker pull ghcr.io/billchurch/webssh2:${{ steps.release_meta.outputs.semver_major }} | |
| \`\`\` | |
| **Image Digest:** \`${IMAGE_DIGEST}\` | |
| **Links:** | |
| - [Docker Hub Repository](https://hub.docker.com/r/billchurch/webssh2) | |
| - [GitHub Container Registry](https://github.com/billchurch/webssh2/pkgs/container/webssh2) | |
| " | |
| # Append Docker section to release notes | |
| gh release edit "$RELEASE_TAG" --notes "${CURRENT_BODY}${DOCKER_SECTION}" |