diff --git a/README.md b/README.md index 18add49..1a534a0 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,17 @@ The `FENV_DOCKER_TAG` argument is automatically provided and ensures your extend The `/cache` directory is backed by a Docker volume that persists between container runs. This makes it an ideal location for build and test caches (as shown in the example above with Go's module cache and golangci-lint cache). +### Image Namespacing + +Extended images are automatically namespaced by project to prevent collisions when multiple projects use fenv. The image name format is `fenv-ext-{project_name}:{tag}`. + +The project name is determined in the following order: +1. Explicit `FENV_PROJECT_NAME` environment variable +2. Git remote repository name (e.g., `myproject` from `git@github.com:user/myproject.git`) +3. Current directory name as a fallback + +This ensures that different projects can have different extended images without interfering with each other, even if they happen to be at the same git commit hash. + ## Local Development Use the `fenv.sh` script to manage your development environment: @@ -182,6 +193,7 @@ jobs: **User-configurable:** - `FENV_FDB_VER`: FoundationDB version (default: `7.1.61`) - `FENV_CACHE_VOLUME`: Custom cache volume name (optional) +- `FENV_PROJECT_NAME`: Project name for namespacing extended images (optional, auto-derived from git remote or directory name) **Auto-computed (available after running fenv):** - `FENV_DOCKER_TAG`: Docker tag for the base fenv image @@ -198,6 +210,7 @@ jobs: |------|-------------|----------|---------| | `fdb_ver` | FoundationDB version | No | `7.1.61` | | `ext_dockerfile` | Path to custom Dockerfile for extending fenv image | No | - | +| `project_name` | Project name for namespacing extended images | No | Repository name | ### GitHub Action Outputs diff --git a/action.yaml b/action.yaml index 82bf3b0..17efb57 100644 --- a/action.yaml +++ b/action.yaml @@ -13,6 +13,11 @@ inputs: required: false default: '' + project_name: + description: 'Project name for namespacing extended images (defaults to repo name)' + required: false + default: '' + outputs: fenv_docker_tag: description: 'Docker image tag for the build container' @@ -90,6 +95,18 @@ runs: env: FENV_FDB_VER: ${{ inputs.fdb_ver }} + - name: Derive project name + if: steps.check_ext_dockerfile.outputs.should_build == 'true' + id: project_name + shell: bash + run: | + if [[ -n "${{ inputs.project_name }}" ]]; then + echo "name=${{ inputs.project_name }}" >> $GITHUB_OUTPUT + else + # Extract repo name from GITHUB_REPOSITORY (org/repo -> repo) + echo "name=$(basename ${{ github.repository }})" >> $GITHUB_OUTPUT + fi + # Create inline bake file for building both images - name: Create bake configuration if: steps.check_ext_dockerfile.outputs.should_build == 'true' @@ -114,10 +131,10 @@ runs: } context = "${{ github.workspace }}" dockerfile = "${{ inputs.ext_dockerfile }}" - tags = ["fenv-ext:${{ steps.docker_ext.outputs.tag }}"] + tags = ["fenv-ext-${{ steps.project_name.outputs.name }}:${{ steps.docker_ext.outputs.tag }}"] platforms = ["linux/amd64"] - cache-from = ["type=gha,scope=fenv-ext-${{ inputs.fdb_ver }}"] - cache-to = ["type=gha,mode=max,scope=fenv-ext-${{ inputs.fdb_ver }}"] + cache-from = ["type=gha,scope=fenv-ext-${{ steps.project_name.outputs.name }}-${{ inputs.fdb_ver }}"] + cache-to = ["type=gha,mode=max,scope=fenv-ext-${{ steps.project_name.outputs.name }}-${{ inputs.fdb_ver }}"] args = { FENV_DOCKER_TAG = "${{ steps.docker.outputs.tag }}" } @@ -158,8 +175,10 @@ runs: # Export extended image variables if [[ "${{ steps.check_ext_dockerfile.outputs.should_build }}" == "true" ]]; then echo "FENV_EXT_DOCKER_TAG=${{ steps.docker_ext.outputs.tag }}" >> $GITHUB_ENV + echo "FENV_PROJECT_NAME=${{ steps.project_name.outputs.name }}" >> $GITHUB_ENV echo "FENV_EXT_IMAGE_BUILT=true" >> $GITHUB_ENV else echo "FENV_EXT_DOCKER_TAG=" >> $GITHUB_ENV + echo "FENV_PROJECT_NAME=" >> $GITHUB_ENV echo "FENV_EXT_IMAGE_BUILT=false" >> $GITHUB_ENV fi diff --git a/fenv.sh b/fenv.sh index d4e31d1..e1a2652 100755 --- a/fenv.sh +++ b/fenv.sh @@ -111,6 +111,35 @@ while [[ $# -gt 0 ]]; do done +# derive_project_name determines a unique name for the project. +# It uses FENV_PROJECT_NAME if set, otherwise derives from git remote +# URL or directory name as a fallback. + +function derive_project_name { + # Use explicit project name if provided + if [[ -n "${FENV_PROJECT_NAME:-}" ]]; then + echo "${FENV_PROJECT_NAME}" + return + fi + + # Try to derive from git remote URL + if git -C "${CALLING_DIR}" remote get-url origin &>/dev/null; then + local remote_url + remote_url="$(git -C "${CALLING_DIR}" remote get-url origin)" + # Extract repo name from URL (handles both https and ssh formats) + # e.g., https://github.com/user/repo.git -> repo + # e.g., git@github.com:user/repo.git -> repo + local repo_name + repo_name="$(basename "${remote_url}" .git)" + echo "${repo_name}" + return + fi + + # Fallback to directory name + basename "${CALLING_DIR}" +} + + # Build variables required by docker commands. FENV_FDB_VER="${FENV_FDB_VER:-7.1.61}" @@ -131,9 +160,14 @@ if [[ -f "${CALLING_DIR}/fenv/docker_tag.sh" ]]; then export FENV_EXT_DOCKER_TAG fi +# Derive project name for namespacing extended images +FENV_PROJECT_NAME="$(derive_project_name)" +echo "FENV_PROJECT_NAME=${FENV_PROJECT_NAME}" +export FENV_PROJECT_NAME + # Select which image to use for compose based on whether --docker was provided. if [[ -n "${EXT_DOCKERFILE:-}" ]]; then - FENV_IMAGE="fenv-ext:${FENV_EXT_DOCKER_TAG}" + FENV_IMAGE="fenv-ext-${FENV_PROJECT_NAME}:${FENV_EXT_DOCKER_TAG}" else FENV_IMAGE="fenv:${FENV_DOCKER_TAG}" fi @@ -163,7 +197,7 @@ if [[ -n "${DO_BUILD:-}" ]]; then (set -x; docker build \ --platform linux/amd64 \ --build-arg "FENV_DOCKER_TAG=${FENV_DOCKER_TAG}" \ - --tag "fenv-ext:${FENV_EXT_DOCKER_TAG}" \ + --tag "fenv-ext-${FENV_PROJECT_NAME}:${FENV_EXT_DOCKER_TAG}" \ --file "${EXT_DOCKERFILE}" \ "${CALLING_DIR}") fi