Skip to content

Build simple-container-com CLI #646

Build simple-container-com CLI

Build simple-container-com CLI #646

Workflow file for this run

name: Build simple-container-com CLI
on:
workflow_dispatch:
push:
branches:
- 'main'
# allow only one concurrent build
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
permissions:
contents: write
jobs:
prepare:
name: Prepare build
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- uses: actions/checkout@v4
- name: Get next version
uses: reecetech/version-increment@2023.10.2
id: version
with:
scheme: "calver"
increment: "patch"
use_api: "true"
build-setup:
name: Build Setup (clean, tools, schemas, lint, fmt)
runs-on: blacksmith-8vcpu-ubuntu-2204
needs: prepare
outputs:
cicd-bot-telegram-token: ${{ steps.telegram-secrets.outputs.cicd-bot-telegram-token }}
cicd-bot-telegram-chat-id: ${{ steps.telegram-secrets.outputs.cicd-bot-telegram-chat-id }}
steps:
- uses: actions/checkout@v4
- uses: fregante/setup-git-user@v2
- name: Set up Go with Blacksmith caching
uses: useblacksmith/setup-go@v6
with:
go-version: '1.25'
- name: install sc tool (latest release)
shell: bash
run: |-
# Install latest SC release to get secrets for embeddings generation
curl -s "https://dist.simple-container.com/sc.sh" | bash
- name: prepare secrets for build
run: |
cat << EOF > ./.sc/cfg.default.yaml
${{ secrets.SC_CONFIG }}
EOF
cat << EOF > ./.sc/cfg.test.yaml
${{ secrets.SC_CONFIG }}
EOF
sc secrets reveal
- name: get openai key
id: get-openai-key
run: |
echo "openai-key=$(sc stack secret-get -s dist openai-api-key 2>/dev/null || echo '')" >> $GITHUB_OUTPUT
- name: prepare sc tool (rebuild)
shell: bash
env:
OPENAI_API_KEY: ${{ steps.get-openai-key.outputs.openai-key }}
SKIP_EMBEDDINGS: "true"
run: |-
git remote set-url origin https://${{ secrets.GITHUB_TOKEN }}@github.com/simple-container-com/api.git
bash <(curl -Ls "https://welder.simple-container.com/welder.sh") run rebuild
- name: clean
run: |
mkdir -p dist
rm -fR dist/*
mkdir -p .sc/stacks/dist/bundle
rm -fR .sc/stacks/dist/bundle/*
mkdir -p docs/site
rm -fR docs/site/*
mkdir -p docs/schemas
rm -fR docs/schemas/*
- name: tools
run: |
cat tools.go | grep _ | awk -F'"' '{print $2}' | xargs -tI % go get %
go mod download
go generate -tags tools
go mod tidy
- name: generate-schemas
run: |
echo "Generating JSON Schema files for Simple Container resources..."
go build -o bin/schema-gen ./cmd/schema-gen
bin/schema-gen docs/schemas
echo "Successfully generated JSON Schema files in docs/schemas/"
- name: fmt
run: |
go mod tidy
bin/gofumpt -l -w ./
bin/golangci-lint run --fix --timeout 3m -v
- name: get telegram secrets
id: telegram-secrets
run: |
echo "cicd-bot-telegram-token=$(./bin/sc stack secret-get -s dist cicd-bot-telegram-token)" >> $GITHUB_OUTPUT
echo "cicd-bot-telegram-chat-id=$(./bin/sc stack secret-get -s dist cicd-bot-telegram-chat-id)" >> $GITHUB_OUTPUT
- name: save schemas cache
uses: actions/cache/save@v4
with:
path: docs/schemas
key: schemas-${{ github.run_id }}
- name: upload bin directory artifacts
uses: actions/upload-artifact@v4
with:
name: bin-tools
path: bin
retention-days: 1
build-platforms:
name: Build sc for ${{ matrix.os }}/${{ matrix.arch }}
runs-on: blacksmith-8vcpu-ubuntu-2204
needs: [prepare, build-setup]
strategy:
matrix:
include:
- os: linux
arch: amd64
- os: darwin
arch: arm64
- os: darwin
arch: amd64
steps:
- uses: actions/checkout@v4
- name: Set up Go with Blacksmith caching
uses: useblacksmith/setup-go@v6
with:
go-version: '1.25'
- name: create build directories
run: |
mkdir -p dist
mkdir -p .sc/stacks/dist/bundle
- name: build sc for ${{ matrix.os }}/${{ matrix.arch }}
env:
GOOS: ${{ matrix.os }}
GOARCH: ${{ matrix.arch }}
CGO_ENABLED: "0"
VERSION: ${{ needs.prepare.outputs.version }}
run: |
echo "Building for ${GOOS}/${GOARCH}..."
if [ "${GOOS}" = "windows" ]; then export EXT=".exe"; else export EXT=""; fi
go build -ldflags "-s -w -X=github.com/simple-container-com/api/internal/build.Version=${VERSION}" -o dist/${GOOS}-${GOARCH}/sc${EXT} ./cmd/sc
tar -czf .sc/stacks/dist/bundle/sc-${GOOS}-${GOARCH}.tar.gz -C dist/${GOOS}-${GOARCH} sc${EXT}
cp .sc/stacks/dist/bundle/sc-${GOOS}-${GOARCH}.tar.gz .sc/stacks/dist/bundle/sc-${GOOS}-${GOARCH}-v${VERSION}.tar.gz
- name: upload build artifacts
uses: actions/upload-artifact@v4
with:
name: sc-${{ matrix.os }}-${{ matrix.arch }}
path: .sc/stacks/dist/bundle/sc-${{ matrix.os }}-${{ matrix.arch }}-*.tar.gz
retention-days: 1
build-binaries:
name: Build ${{ matrix.target }}
runs-on: blacksmith-8vcpu-ubuntu-2204
needs: [prepare, build-setup]
strategy:
matrix:
include:
- target: github-actions
cmd: github-actions
output: dist/github-actions
- target: cloud-helpers
cmd: cloud-helpers
output: dist/cloud-helpers
steps:
- uses: actions/checkout@v4
- name: Set up Go with Blacksmith caching
uses: useblacksmith/setup-go@v6
with:
go-version: '1.25'
- name: create build directories
run: |
mkdir -p dist
- name: build ${{ matrix.target }}
env:
VERSION: ${{ needs.prepare.outputs.version }}
CGO_ENABLED: "0"
run: |
go build -a -installsuffix cgo -ldflags "-s -w -X=github.com/simple-container-com/api/internal/build.Version=${VERSION}" -o ${{ matrix.output }} ./cmd/${{ matrix.cmd }}
- name: upload ${{ matrix.target }} binary
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.target }}-binary
path: ${{ matrix.output }}
retention-days: 1
build-github-actions-staging:
name: Build github-actions-staging
runs-on: blacksmith-8vcpu-ubuntu-2204
needs: [prepare, build-setup]
steps:
- uses: actions/checkout@v4
- name: Set up Go with Blacksmith caching
uses: useblacksmith/setup-go@v6
with:
go-version: '1.25'
- name: build github-actions-staging
env:
VERSION: ${{ needs.prepare.outputs.version }}
CGO_ENABLED: "0"
run: |
mkdir -p bin
go build -ldflags "-s -w -X=github.com/simple-container-com/api/internal/build.Version=${VERSION}" -a -installsuffix cgo -o bin/github-actions ./cmd/github-actions
- name: upload github-actions-staging binary
uses: actions/upload-artifact@v4
with:
name: github-actions-staging-binary
path: bin/github-actions
retention-days: 1
test:
name: Run tests
runs-on: blacksmith-8vcpu-ubuntu-2204
needs: [prepare, build-setup]
steps:
- uses: actions/checkout@v4
- name: Set up Go with Blacksmith caching
uses: useblacksmith/setup-go@v6
with:
go-version: '1.25'
- name: test
run: |
go test ./...
build-docs:
name: Build documentation
runs-on: ubuntu-latest
needs: [prepare, build-setup]
steps:
- uses: actions/checkout@v4
- name: restore cached schemas
uses: actions/cache@v4
with:
path: docs/schemas
key: schemas-${{ github.run_id }}
- name: build docs
run: |
docker run --rm -v $PWD/docs:/docs -w /docs python:3.9.18 sh -c "pip install -r requirements.txt && PATH=\$PATH:~/.local/bin mkdocs build"
- name: upload docs artifact
uses: actions/upload-artifact@v4
with:
name: docs-site
path: docs/site
retention-days: 1
docker-build:
name: Docker build and push ${{ matrix.image }}
runs-on: blacksmith-8vcpu-ubuntu-2204
needs: [prepare, build-setup, build-platforms, build-binaries, build-github-actions-staging, test, build-docs]
strategy:
matrix:
include:
- image: kubectl
dockerfile: kubectl.Dockerfile
tags: |
simplecontainer/kubectl:latest
simplecontainer/kubectl:${{ needs.prepare.outputs.version }}
- image: caddy
dockerfile: caddy.Dockerfile
tags: |
simplecontainer/caddy:latest
simplecontainer/caddy:${{ needs.prepare.outputs.version }}
- image: github-actions
dockerfile: github-actions.Dockerfile
tags: |
simplecontainer/github-actions:latest
simplecontainer/github-actions:${{ needs.prepare.outputs.version }}
- image: github-actions-staging
dockerfile: github-actions-staging.Dockerfile
tags: simplecontainer/github-actions:staging
- image: cloud-helpers-aws
dockerfile: cloud-helpers.aws.Dockerfile
tags: |
simplecontainer/cloud-helpers:aws-latest
simplecontainer/cloud-helpers:aws-${{ needs.prepare.outputs.version }}
steps:
- uses: actions/checkout@v4
- name: download github-actions-staging binary
if: matrix.image == 'github-actions-staging'
uses: actions/download-artifact@v4
with:
name: github-actions-staging-binary
path: bin
- name: download github-actions binary
if: matrix.image == 'github-actions'
uses: actions/download-artifact@v4
with:
name: github-actions-binary
path: dist
- name: download cloud-helpers binary
if: matrix.image == 'cloud-helpers-aws'
uses: actions/download-artifact@v4
with:
name: cloud-helpers-binary
path: dist
- name: install sc tool (latest release)
shell: bash
run: |-
# Install latest SC release to get secrets for embeddings generation
curl -s "https://dist.simple-container.com/sc.sh" | bash
- name: prepare secrets for build
run: |
cat << EOF > ./.sc/cfg.default.yaml
${{ secrets.SC_CONFIG }}
EOF
cat << EOF > ./.sc/cfg.test.yaml
${{ secrets.SC_CONFIG }}
EOF
sc secrets reveal
- name: Setup Docker Buildx with advanced caching
uses: docker/setup-buildx-action@v3
with:
driver-opts: |
image=moby/buildkit:buildx-stable-1
buildkitd-flags: --allow-insecure-entitlement security.insecure
- name: Docker login using SC secrets
run: |
sc stack secret-get -s dist dockerhub-cicd-token | docker login --username simplecontainer --password-stdin
- name: Build and push ${{ matrix.image }} image
env:
DOCKER_BUILDKIT: 1
VERSION: ${{ needs.prepare.outputs.version }}
run: |
mapfile -t tags <<< "${{ matrix.tags }}"
for tag in "${tags[@]}"; do
# Skip empty tags caused by trailing newlines in multi-line YAML
if [ -n "$tag" ]; then
docker buildx build \
--platform linux/amd64 \
--cache-from type=gha \
--cache-to type=gha,mode=max \
--file ${{ matrix.dockerfile }} \
--tag "$tag" \
--push \
.
fi
done
docker-finalize:
name: Docker finalize (tag-release, deploy)
runs-on: blacksmith-8vcpu-ubuntu-2204
needs: [prepare, build-setup, build-platforms, build-binaries, build-github-actions-staging, test, build-docs, docker-build]
steps:
- uses: actions/checkout@v4
- uses: fregante/setup-git-user@v2
- name: install sc tool (latest release)
shell: bash
run: |-
# Install latest SC release to get secrets for embeddings generation
curl -s "https://dist.simple-container.com/sc.sh" | bash
- name: prepare secrets for build
run: |
cat << EOF > ./.sc/cfg.default.yaml
${{ secrets.SC_CONFIG }}
EOF
cat << EOF > ./.sc/cfg.test.yaml
${{ secrets.SC_CONFIG }}
EOF
sc secrets reveal
- name: download all build artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: download bin tools artifact
uses: actions/download-artifact@v4
with:
name: bin-tools
path: bin
- name: fix bin tools permissions
run: chmod +x bin/*
- name: download docs artifact
uses: actions/download-artifact@v4
with:
name: docs-site
path: docs/site
- name: copy build artifacts to dist bundle
run: |
mkdir -p .sc/stacks/dist/bundle
cp artifacts/sc-*/*.tar.gz .sc/stacks/dist/bundle/ 2>/dev/null || true
- name: finalize dist bundle setup
env:
VERSION: ${{ needs.prepare.outputs.version }}
run: |
cp sc.sh .sc/stacks/dist/bundle/sc.sh
sed -i -e 's/VERSION="0\.0\.0"/VERSION="${VERSION}"/g' .sc/stacks/dist/bundle/sc.sh
echo "${VERSION}" > .sc/stacks/dist/bundle/version
- name: Run tag-release task after images are built
env:
VERSION: ${{ needs.prepare.outputs.version }}
run: |-
git remote set-url origin https://${{ secrets.GITHUB_TOKEN }}@github.com/simple-container-com/api.git
bash <(curl -Ls "https://welder.simple-container.com/welder.sh") run tag-release
- name: publish sc tool
shell: bash
env:
VERSION: ${{ needs.prepare.outputs.version }}
run: |-
bash <(curl -Ls "https://welder.simple-container.com/welder.sh") deploy -e prod --timestamps
finalize:
name: Finalize build and deploy for ${{ needs.prepare.outputs.stack-name }}
runs-on: ubuntu-latest
if: ${{ always() }}
permissions:
contents: write
needs:
- prepare
- build-setup
- docker-finalize
steps:
- uses: actions/checkout@v4
if: ${{ always() }}
- name: Extract git reference
id: extract_git_ref
if: ${{ always() }}
shell: bash
run: |-
cat <<'EOF' > /tmp/commit_message.txt
${{ github.event.head_commit.message || github.event.workflow_run.head_commit.message }}
EOF
message="$(cat /tmp/commit_message.txt | tr -d '\n')"
# Truncate message if too long for Telegram (max ~200 chars to leave room for other content)
if [ ${#message} -gt 200 ]; then
# Take first 80 chars and last 80 chars with separator
truncated_message="${message:0:80}...${message: -80}"
message="$truncated_message"
fi
echo "branch=$GITHUB_REF_NAME" >> $GITHUB_OUTPUT
echo "message=$message" >> $GITHUB_OUTPUT
echo "author=$GITHUB_ACTOR" >> $GITHUB_OUTPUT
echo "url=$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" >> $GITHUB_OUTPUT
# Notify telegram
- uses: yanzay/notify-telegram@v0.1.0
if: ${{ success() && !contains(needs.*.result, 'failure') }}
continue-on-error: true
with:
chat: ${{ needs.build-setup.outputs.cicd-bot-telegram-chat-id }}
token: ${{ needs.build-setup.outputs.cicd-bot-telegram-token }}
status: ✅ success (${{ steps.extract_git_ref.outputs.branch }}) (v${{ needs.prepare.outputs.version }}) - ${{ steps.extract_git_ref.outputs.message }} by ${{ steps.extract_git_ref.outputs.author }}
- uses: yanzay/notify-telegram@v0.1.0
if: ${{ failure() || contains(needs.*.result, 'failure') }}
continue-on-error: true
with:
chat: ${{ needs.build-setup.outputs.cicd-bot-telegram-chat-id }}
token: ${{ needs.build-setup.outputs.cicd-bot-telegram-token }}
status: ❗ failure (${{ steps.extract_git_ref.outputs.branch }}) - ${{ steps.extract_git_ref.outputs.message }} by ${{ steps.extract_git_ref.outputs.author }}
- name: Build failed due to previously failed steps
id: fail_if_needed
if: ${{ failure() || contains(needs.*.result, 'failure') }}
shell: bash
run: |-
exit 1