name: Generic Container CI/CD on: workflow_call: inputs: image_name: description: Fully qualified Gitea Registry image repository without a tag required: true type: string dockerfile: required: false default: Dockerfile type: string build_context: required: false default: . type: string cache_image: description: Optional internal image carrying BuildKit inline cache required: false default: "" type: string test_command: description: Optional source-level test command required: false default: "" type: string test_target: description: Optional Dockerfile target that performs build-time tests required: false default: "" type: string deploy_service: description: Dev service to candidate-test and promote required: false default: "" type: string deploy_host: description: Restricted Dev deployment host required: false default: "" type: string secrets: REGISTRY_USERNAME: required: true REGISTRY_PASSWORD: required: true DEV_DEPLOY_SSH_KEY: required: false jobs: test-build-publish: runs-on: ubuntu-22.04 steps: - name: Configure Git transport run: git config --global http.version HTTP/1.1 - uses: https://gitea.waternetwork.cn/actions/checkout@v4 with: fetch-depth: 1 - name: Source tests if: ${{ inputs.test_command != '' }} run: ${{ inputs.test_command }} - name: Login and publish candidate image env: REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }} REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }} run: | set -eu registry="$(printf '%s' '${{ inputs.image_name }}' | cut -d/ -f1)" printf '%s' "$REGISTRY_PASSWORD" | docker login "$registry" -u "$REGISTRY_USERNAME" --password-stdin if [ -n "${{ inputs.cache_image }}" ] && ! docker image inspect "${{ inputs.cache_image }}" >/dev/null 2>&1; then echo "Required CI cache image is not present on this Runner: ${{ inputs.cache_image }}" echo "Import the cache image locally before starting this workflow." exit 1 fi - name: Build immutable candidate image run: | set -eu cache_args=() if [ -n "${{ inputs.cache_image }}" ]; then cache_args+=(--cache-from "${{ inputs.cache_image }}") fi if [ -n "${{ inputs.test_target }}" ]; then docker build --pull=false "${cache_args[@]}" --target "${{ inputs.test_target }}" \ -f "${{ inputs.dockerfile }}" "${{ inputs.build_context }}" fi docker build --pull=false "${cache_args[@]}" -f "${{ inputs.dockerfile }}" \ -t "${{ inputs.image_name }}:sha-${{ gitea.sha }}" "${{ inputs.build_context }}" docker push "${{ inputs.image_name }}:sha-${{ gitea.sha }}" - name: Configure restricted Dev deployment key if: ${{ inputs.deploy_service != '' && inputs.deploy_host != '' }} env: DEV_DEPLOY_SSH_KEY: ${{ secrets.DEV_DEPLOY_SSH_KEY }} run: | set -eu test -n "$DEV_DEPLOY_SSH_KEY" install -d -m 700 ~/.ssh printf '%s\n' "$DEV_DEPLOY_SSH_KEY" > ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519 ssh-keyscan -H "${{ inputs.deploy_host }}" >> ~/.ssh/known_hosts - name: Transfer candidate image to Dev if: ${{ inputs.deploy_service != '' && inputs.deploy_host != '' }} run: | set -euo pipefail docker save "${{ inputs.image_name }}:sha-${{ gitea.sha }}" | \ ssh -i ~/.ssh/id_ed25519 cicd-deploy@"${{ inputs.deploy_host }}" \ "load ${{ inputs.deploy_service }} ${{ inputs.image_name }}:sha-${{ gitea.sha }}" - name: Candidate verification on Dev if: ${{ inputs.deploy_service != '' && inputs.deploy_host != '' }} run: | set -eu ssh -i ~/.ssh/id_ed25519 cicd-deploy@"${{ inputs.deploy_host }}" \ "candidate ${{ inputs.deploy_service }} ${{ inputs.image_name }}:sha-${{ gitea.sha }}" - name: Promote tagged release after candidate check if: ${{ startsWith(gitea.ref, 'refs/tags/v') && inputs.deploy_service != '' && inputs.deploy_host != '' }} env: DEV_DEPLOY_SSH_KEY: ${{ secrets.DEV_DEPLOY_SSH_KEY }} run: | set -eu ssh -i ~/.ssh/id_ed25519 cicd-deploy@"${{ inputs.deploy_host }}" \ "promote ${{ inputs.deploy_service }} ${{ inputs.image_name }}:sha-${{ gitea.sha }}"