diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..a6bd8d83 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,9 @@ +# Ignore everything +* + +# Allow only what the Go build needs +!go.mod +!go.sum +!main.go +!cmd/ +!internal/ diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml index 2bd19bfc..a4180821 100644 --- a/.github/workflows/dependencies.yml +++ b/.github/workflows/dependencies.yml @@ -70,6 +70,7 @@ jobs: go mod tidy sed -i "s/cimg\/go:.*/cimg\/go:${VERSION#go}/" .circleci/config.yml sed -i "s/go-version: .*/go-version: \"${VERSION#go}\"/" .github/workflows/tests.yml + sed -i "s/golang:[0-9.]*-trixie/golang:${VERSION#go}-trixie/" docker/Dockerfile.node docker/Dockerfile.python env: VERSION: ${{ steps.version.outputs.latest }} - name: Open a change request diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 00000000..b7055f0c --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,78 @@ +name: Publish Docker Images + +on: + release: + types: [published] + +env: + REGISTRY: ghcr.io + IMAGE_NAME: slackapi/slack-cli + +jobs: + docker: + name: Build and push (${{ matrix.variant }}) + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + strategy: + fail-fast: false + matrix: + variant: [node, python] + include: + - variant: node + dockerfile: docker/Dockerfile.node + - variant: python + dockerfile: docker/Dockerfile.python + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: Set up QEMU + uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 + + - name: Log in to GHCR + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract version + id: version + run: | + TAG="${{ github.event.release.tag_name }}" + echo "tag=${TAG}" >> "$GITHUB_OUTPUT" + echo "stripped=${TAG#v}" >> "$GITHUB_OUTPUT" + echo "prerelease=${{ github.event.release.prerelease }}" >> "$GITHUB_OUTPUT" + + - name: Generate Docker metadata + id: meta + uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + flavor: | + latest=false + tags: | + type=raw,value=${{ steps.version.outputs.stripped }}-${{ matrix.variant }} + type=raw,value=${{ steps.version.outputs.tag }}-${{ matrix.variant }} + type=raw,value=${{ matrix.variant }},enable=${{ steps.version.outputs.prerelease == 'false' }} + type=raw,value=latest-${{ matrix.variant }},enable=${{ steps.version.outputs.prerelease == 'false' }} + + - name: Build and push + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6 + with: + context: . + file: ${{ matrix.dockerfile }} + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + build-args: | + VERSION=${{ steps.version.outputs.tag }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/docker/Dockerfile.node b/docker/Dockerfile.node new file mode 100644 index 00000000..a8550424 --- /dev/null +++ b/docker/Dockerfile.node @@ -0,0 +1,43 @@ +# Copyright 2022-2026 Salesforce, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM golang:1.26.3-trixie AS builder + +ARG VERSION=v0.0.0-dev +ARG TARGETARCH + +WORKDIR /src + +COPY go.mod go.sum ./ +RUN go mod download + +COPY . . + +RUN CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH} \ + go build -ldflags="-s -w -X 'github.com/slackapi/slack-cli/internal/version.Version=${VERSION}'" \ + -o /out/slack . + +FROM mcr.microsoft.com/devcontainers/javascript-node:24-trixie + +COPY --from=builder --chown=node:node /out/slack /home/node/.slack/bin/slack +ENV PATH="/home/node/.slack/bin:${PATH}" + +LABEL org.opencontainers.image.title="Slack CLI (Node.js)" +LABEL org.opencontainers.image.description="Slack Platform CLI development environment with Node.js" +LABEL org.opencontainers.image.source="https://github.com/slackapi/slack-cli" +LABEL org.opencontainers.image.licenses="Apache-2.0" +LABEL org.opencontainers.image.vendor="Salesforce, Inc." +LABEL devcontainer.metadata='[{"remoteUser": "node"}]' + +USER node diff --git a/docker/Dockerfile.python b/docker/Dockerfile.python new file mode 100644 index 00000000..1578c066 --- /dev/null +++ b/docker/Dockerfile.python @@ -0,0 +1,43 @@ +# Copyright 2022-2026 Salesforce, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM golang:1.26.3-trixie AS builder + +ARG VERSION=v0.0.0-dev +ARG TARGETARCH + +WORKDIR /src + +COPY go.mod go.sum ./ +RUN go mod download + +COPY . . + +RUN CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH} \ + go build -ldflags="-s -w -X 'github.com/slackapi/slack-cli/internal/version.Version=${VERSION}'" \ + -o /out/slack . + +FROM mcr.microsoft.com/devcontainers/python:3.14-trixie + +COPY --from=builder --chown=vscode:vscode /out/slack /home/vscode/.slack/bin/slack +ENV PATH="/home/vscode/.slack/bin:${PATH}" + +LABEL org.opencontainers.image.title="Slack CLI (Python)" +LABEL org.opencontainers.image.description="Slack Platform CLI development environment with Python" +LABEL org.opencontainers.image.source="https://github.com/slackapi/slack-cli" +LABEL org.opencontainers.image.licenses="Apache-2.0" +LABEL org.opencontainers.image.vendor="Salesforce, Inc." +LABEL devcontainer.metadata='[{"remoteUser": "vscode"}]' + +USER vscode