diff --git a/.github/workflows/devcontainer.yml b/.github/workflows/devcontainer.yml new file mode 100644 index 00000000..c95ec23c --- /dev/null +++ b/.github/workflows/devcontainer.yml @@ -0,0 +1,47 @@ +name: DevContainer +concurrency: + cancel-in-progress: true + group: ${{ github.workflow }}-${{ github.ref }} +jobs: + dev-container-publish: + permissions: + contents: read + packages: write + runs-on: ubuntu-latest + steps: + - uses: docker/setup-buildx-action@v3 + - uses: docker/login-action@v3 + with: + password: ${{ secrets.GITHUB_TOKEN }} + registry: ghcr.io + username: ${{ github.actor }} + - name: Build and push dev container + env: + SOURCE_DATE_EPOCH: 0 + uses: docker/build-push-action@v5 + with: + build-args: | + PYTHON_VERSION=${{ matrix.python-version }} + cache-from: type=registry,ref=ghcr.io/${{ github.repository }}:build-cache-dev-py${{ matrix.python-version }} + cache-to: type=registry,ref=ghcr.io/${{ github.repository }}:build-cache-dev-py${{ matrix.python-version }},mode=max + file: .devcontainer/Dockerfile + provenance: false + push: true + tags: | + ghcr.io/${{ github.repository }}:dev-py${{ matrix.python-version }} + target: dev + strategy: + matrix: + python-version: + - '3.8' + - '3.9' + - '3.10' + - '3.11' + - '3.12' +on: + push: + branches: + - main + paths: + - .devcontainer/Dockerfile + workflow_dispatch: null diff --git a/.gitlab/workflows/devcontainer.yml b/.gitlab/workflows/devcontainer.yml new file mode 100644 index 00000000..abf9497a --- /dev/null +++ b/.gitlab/workflows/devcontainer.yml @@ -0,0 +1,37 @@ +dev-container-publish: + image: docker:latest + parallel: + matrix: + - PYTHON_VERSION: + - '3.8' + - '3.9' + - '3.10' + - '3.11' + - '3.12' + rules: + - changes: + - .devcontainer/Dockerfile + if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH + script: + - docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY} + - docker context create builder + - docker buildx create builder --name container --driver docker-container --use + - docker buildx inspect --bootstrap --builder container + - | + docker buildx build . \ + --build-arg PYTHON_VERSION=${PYTHON_VERSION} \ + --cache-from type=registry,ref=${CI_REGISTRY_IMAGE}:build-cache-dev-py${PYTHON_VERSION} \ + --cache-to type=registry,ref=${CI_REGISTRY_IMAGE}:build-cache-dev-py${PYTHON_VERSION},mode=max \ + --file .devcontainer/Dockerfile \ + --provenance false \ + --push \ + --tag ${CI_REGISTRY_IMAGE}:dev-py${PYTHON_VERSION} \ + --tag ${CI_REGISTRY_IMAGE}:dev-py${PYTHON_VERSION}-${CI_COMMIT_TAG} \ + --target dev + services: + - docker:dind + stage: build + variables: + DOCKER_TLS_CERTDIR: /certs + PYTHON_VERSION: ${PYTHON_VERSION} + SOURCE_DATE_EPOCH: 0 diff --git a/.gitlab/workflows/release.yml b/.gitlab/workflows/release.yml index 1409a0b3..fcac6348 100644 --- a/.gitlab/workflows/release.yml +++ b/.gitlab/workflows/release.yml @@ -84,6 +84,7 @@ pages: paths: - public needs: + - pages-build - release-publish rules: - if: $CI_COMMIT_TAG =~ /^v?(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-?(a|b|rc)(0|[1-9][0-9]*)?)?$/ diff --git a/README.md b/README.md index 69f5fb65..721c09e7 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ A Python project template covering the entire development lifecycle with various [![CI](https://github.com/serious-scaffold/ss-python/actions/workflows/ci.yml/badge.svg)](https://github.com/serious-scaffold/ss-python/actions/workflows/ci.yml) [![Release](https://github.com/serious-scaffold/ss-python/actions/workflows/release.yml/badge.svg)](https://github.com/serious-scaffold/ss-python/actions/workflows/release.yml) +[![DevContainer](https://github.com/serious-scaffold/ss-python/actions/workflows/devcontainer.yml/badge.svg)](https://github.com/serious-scaffold/ss-python/actions/workflows/devcontainer.yml) [![Coverage](https://img.shields.io/endpoint?url=https://serious-scaffold.github.io/ss-python/_static/badges/coverage.json)](https://serious-scaffold.github.io/ss-python/reports/coverage) [![PyPI](https://img.shields.io/pypi/v/ss-python)](https://pypi.org/project/ss-python/) [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/ss-python)](https://pypi.org/project/ss-python/) diff --git a/includes/variable.jinja b/includes/variable.jinja index 12244933..2aac8602 100644 --- a/includes/variable.jinja +++ b/includes/variable.jinja @@ -43,6 +43,7 @@ [% if repo_host_type == 'github.com' -%] [![CI](https://{{ repo_url() }}/actions/workflows/ci.yml/badge.svg)](https://{{ repo_url() }}/actions/workflows/ci.yml) [![Release](https://{{ repo_url() }}/actions/workflows/release.yml/badge.svg)](https://{{ repo_url() }}/actions/workflows/release.yml) +[![DevContainer](https://{{ repo_url() }}/actions/workflows/devcontainer.yml/badge.svg)](https://{{ repo_url() }}/actions/workflows/devcontainer.yml) [%- elif repo_host_type == 'gitlab.com' or repo_host_type == 'gitlab-self-managed' -%] [![pipeline status](https://{{ repo_url() }}/badges/main/pipeline.svg)](https://{{ repo_url() }}/-/commits/main) [%- endif %] diff --git a/template/[% if repo_host_type == 'github.com' %].github[% endif %]/workflows/devcontainer.yml.jinja b/template/[% if repo_host_type == 'github.com' %].github[% endif %]/workflows/devcontainer.yml.jinja new file mode 100644 index 00000000..24f3a507 --- /dev/null +++ b/template/[% if repo_host_type == 'github.com' %].github[% endif %]/workflows/devcontainer.yml.jinja @@ -0,0 +1,58 @@ +[% from pathjoin("includes", "version_compare.jinja") import version_between -%] +name: DevContainer +concurrency: + cancel-in-progress: true + group: {{ '${{ github.workflow }}-${{ github.ref }}' }} +jobs: + dev-container-publish: + permissions: + contents: read + packages: write + runs-on: ubuntu-latest + steps: + - uses: docker/setup-buildx-action@v3 + - uses: docker/login-action@v3 + with: + password: {{ '${{ secrets.GITHUB_TOKEN }}' }} + registry: ghcr.io + username: {{ '${{ github.actor }}' }} + - name: Build and push dev container + env: + SOURCE_DATE_EPOCH: 0 + uses: docker/build-push-action@v5 + with: + build-args: | + PYTHON_VERSION={{ '${{ matrix.python-version }}' }} + cache-from: type=registry,ref=ghcr.io/{{ '${{ github.repository }}' }}:build-cache-dev-py{{ '${{ matrix.python-version }}' }} + cache-to: type=registry,ref=ghcr.io/{{ '${{ github.repository }}' }}:build-cache-dev-py{{ '${{ matrix.python-version }}' }},mode=max + file: .devcontainer/Dockerfile + provenance: false + push: true + tags: | + ghcr.io/{{ '${{ github.repository }}' }}:dev-py{{ '${{ matrix.python-version }}' }} + target: dev + strategy: + matrix: + python-version: +[%- if version_between("3.8", min_py, max_py) %] + - '3.8' +[%- endif %] +[%- if version_between("3.9", min_py, max_py) %] + - '3.9' +[%- endif %] +[%- if version_between("3.10", min_py, max_py) %] + - '3.10' +[%- endif %] +[%- if version_between("3.11", min_py, max_py) %] + - '3.11' +[%- endif %] +[%- if version_between("3.12", min_py, max_py) %] + - '3.12' +[%- endif %] +on: + push: + branches: + - main + paths: + - .devcontainer/Dockerfile + workflow_dispatch: null diff --git a/template/[% if repo_host_type == 'gitlab.com' or repo_host_type == 'gitlab-self-managed' %].gitlab[% endif %]/workflows/devcontainer.yml.jinja b/template/[% if repo_host_type == 'gitlab.com' or repo_host_type == 'gitlab-self-managed' %].gitlab[% endif %]/workflows/devcontainer.yml.jinja new file mode 100644 index 00000000..3b33a5f0 --- /dev/null +++ b/template/[% if repo_host_type == 'gitlab.com' or repo_host_type == 'gitlab-self-managed' %].gitlab[% endif %]/workflows/devcontainer.yml.jinja @@ -0,0 +1,48 @@ +[% from pathjoin("includes", "version_compare.jinja") import version_between -%] +dev-container-publish: + image: docker:latest + parallel: + matrix: + - PYTHON_VERSION: +[%- if version_between("3.8", min_py, max_py) %] + - '3.8' +[%- endif %] +[%- if version_between("3.9", min_py, max_py) %] + - '3.9' +[%- endif %] +[%- if version_between("3.10", min_py, max_py) %] + - '3.10' +[%- endif %] +[%- if version_between("3.11", min_py, max_py) %] + - '3.11' +[%- endif %] +[%- if version_between("3.12", min_py, max_py) %] + - '3.12' +[%- endif %] + rules: + - changes: + - .devcontainer/Dockerfile + if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH + script: + - docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY} + - docker context create builder + - docker buildx create builder --name container --driver docker-container --use + - docker buildx inspect --bootstrap --builder container + - | + docker buildx build . \ + --build-arg PYTHON_VERSION=${PYTHON_VERSION} \ + --cache-from type=registry,ref=${CI_REGISTRY_IMAGE}:build-cache-dev-py${PYTHON_VERSION} \ + --cache-to type=registry,ref=${CI_REGISTRY_IMAGE}:build-cache-dev-py${PYTHON_VERSION},mode=max \ + --file .devcontainer/Dockerfile \ + --provenance false \ + --push \ + --tag ${CI_REGISTRY_IMAGE}:dev-py${PYTHON_VERSION} \ + --tag ${CI_REGISTRY_IMAGE}:dev-py${PYTHON_VERSION}-${CI_COMMIT_TAG} \ + --target dev + services: + - docker:dind + stage: build + variables: + DOCKER_TLS_CERTDIR: /certs + PYTHON_VERSION: ${PYTHON_VERSION} + SOURCE_DATE_EPOCH: 0 diff --git a/template/[% if repo_host_type == 'gitlab.com' or repo_host_type == 'gitlab-self-managed' %].gitlab[% endif %]/workflows/release.yml.jinja b/template/[% if repo_host_type == 'gitlab.com' or repo_host_type == 'gitlab-self-managed' %].gitlab[% endif %]/workflows/release.yml.jinja index 454fd4f6..fca26dfb 100644 --- a/template/[% if repo_host_type == 'gitlab.com' or repo_host_type == 'gitlab-self-managed' %].gitlab[% endif %]/workflows/release.yml.jinja +++ b/template/[% if repo_host_type == 'gitlab.com' or repo_host_type == 'gitlab-self-managed' %].gitlab[% endif %]/workflows/release.yml.jinja @@ -95,6 +95,7 @@ pages: paths: - public needs: + - pages-build - release-publish rules: - if: $CI_COMMIT_TAG =~ /^v?(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-?(a|b|rc)(0|[1-9][0-9]*)?)?$/