Skip to content

Commit 2d1e258

Browse files
Merge pull request #13 from pulp/docker-build
Adding workflow for building docker images (PRs and release)
2 parents 46d257c + a9c4bfe commit 2d1e258

File tree

7 files changed

+468
-6
lines changed

7 files changed

+468
-6
lines changed

.dockerignore

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,43 @@
1-
demo/assets/keys/gpg/
2-
demo/assets/certs/
1+
# Version control
2+
.git/
3+
.gitignore
4+
.github/
5+
6+
# Development environment
7+
.devcontainer/
38
.claude/
4-
.coverage
59
venv/
6-
__pycache__/
10+
11+
# Tests and coverage
12+
**/tests/
13+
**/unit_tests/
14+
.pytest_cache/
15+
.coverage
16+
htmlcov/
17+
pytest.ini
18+
19+
# Development configs
20+
pylint.rc
21+
Makefile
22+
23+
# Documentation
24+
*.md
25+
!README.md
26+
docs/
27+
28+
# Demo files
29+
demo/
30+
31+
# Python cache
32+
__pycache__/
33+
*.pyc
34+
*.pyo
35+
*.pyd
36+
.Python
37+
*.egg-info/
38+
39+
# IDE files
40+
.vscode/
41+
.idea/
42+
*.swp
43+
.DS_Store

.github/workflows/docker-build.yml

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
name: Build and Push Docker Images
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
tags:
8+
- 'v*.*.*'
9+
- '[0-9]+.[0-9]+.[0-9]+'
10+
pull_request:
11+
branches:
12+
- main
13+
workflow_dispatch:
14+
workflow_call:
15+
16+
env:
17+
IMAGE_NAME: pulp-manager
18+
19+
jobs:
20+
build-and-push:
21+
name: Build and Push Docker Image
22+
runs-on: ubuntu-latest
23+
permissions:
24+
contents: read
25+
packages: write
26+
id-token: write
27+
28+
steps:
29+
- name: Checkout code
30+
uses: actions/checkout@v4
31+
with:
32+
submodules: recursive
33+
34+
- name: Set up Docker Buildx
35+
uses: docker/setup-buildx-action@v3
36+
37+
- name: Determine registries to push to
38+
id: registries
39+
run: |
40+
# Always include ghcr.io
41+
registries="ghcr.io"
42+
43+
# Add docker.io and quay.io for release tags
44+
if [[ "${{ github.ref }}" == refs/tags/* ]]; then
45+
registries="ghcr.io docker.io quay.io"
46+
fi
47+
48+
echo "registries=${registries}" >> $GITHUB_OUTPUT
49+
echo "Will push to: ${registries}"
50+
51+
- name: Log in to GitHub Container Registry
52+
uses: docker/login-action@v3
53+
with:
54+
registry: ghcr.io
55+
username: ${{ github.actor }}
56+
password: ${{ secrets.GITHUB_TOKEN }}
57+
58+
- name: Log in to Docker Hub
59+
if: startsWith(github.ref, 'refs/tags/')
60+
uses: docker/login-action@v3
61+
with:
62+
registry: docker.io
63+
username: ${{ secrets.DOCKER_BOT_USERNAME }}
64+
password: ${{ secrets.DOCKER_BOT_PASSWORD }}
65+
66+
- name: Log in to Quay.io
67+
if: startsWith(github.ref, 'refs/tags/')
68+
uses: docker/login-action@v3
69+
with:
70+
registry: quay.io
71+
username: ${{ secrets.QUAY_BOT_USERNAME }}
72+
password: ${{ secrets.QUAY_BOT_PASSWORD }}
73+
74+
- name: Determine tags
75+
id: tags
76+
run: |
77+
tags=""
78+
79+
if [[ "${{ github.ref }}" == refs/tags/* ]]; then
80+
# Release tag (e.g., v1.2.3)
81+
version="${{ github.ref_name }}"
82+
version="${version#v}" # Remove 'v' prefix
83+
major=$(echo $version | cut -d. -f1)
84+
minor=$(echo $version | cut -d. -f1-2)
85+
tags="${version} ${minor} ${major} latest"
86+
elif [ "${{ github.ref_name }}" == "main" ]; then
87+
# Main branch
88+
tags="main latest"
89+
elif [ "${{ github.event_name }}" == "pull_request" ]; then
90+
# PR
91+
tags="pr-${{ github.event.pull_request.number }}"
92+
else
93+
# Other branches
94+
tags="${{ github.ref_name }}"
95+
fi
96+
97+
# Add SHA tag for traceability
98+
sha_short=$(echo ${{ github.sha }} | cut -c1-7)
99+
tags="${tags} sha-${sha_short}"
100+
101+
echo "tags=${tags}" >> $GITHUB_OUTPUT
102+
echo "Will use tags: ${tags}"
103+
104+
- name: Build Docker image
105+
uses: docker/build-push-action@v5
106+
with:
107+
context: .
108+
file: ./Dockerfile
109+
push: false
110+
load: true
111+
tags: pulp/${{ env.IMAGE_NAME }}:ci
112+
labels: |
113+
org.opencontainers.image.title=Pulp Manager
114+
org.opencontainers.image.description=FastAPI-based orchestration and management for multiple Pulp 3 servers
115+
org.opencontainers.image.vendor=Pulp
116+
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
117+
org.opencontainers.image.revision=${{ github.sha }}
118+
cache-from: type=gha
119+
cache-to: type=gha,mode=max
120+
platforms: linux/amd64
121+
122+
- name: Push to registries
123+
run: |
124+
for registry in ${{ steps.registries.outputs.registries }}; do
125+
echo "Pushing to ${registry}..."
126+
for tag in ${{ steps.tags.outputs.tags }}; do
127+
echo " Tagging and pushing ${registry}/pulp/${{ env.IMAGE_NAME }}:${tag}"
128+
docker tag pulp/${{ env.IMAGE_NAME }}:ci ${registry}/pulp/${{ env.IMAGE_NAME }}:${tag}
129+
docker push ${registry}/pulp/${{ env.IMAGE_NAME }}:${tag}
130+
done
131+
done
132+
133+
- name: Generate artifact attestation
134+
if: github.event_name != 'pull_request'
135+
uses: actions/attest-build-provenance@v1
136+
with:
137+
subject-name: ghcr.io/pulp/${{ env.IMAGE_NAME }}
138+
subject-digest: ${{ hashFiles('Dockerfile') }}
139+
push-to-registry: true

.github/workflows/release.yml

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*.*.*'
7+
- '[0-9]+.[0-9]+.[0-9]+'
8+
workflow_dispatch:
9+
inputs:
10+
tag:
11+
description: 'Tag to release'
12+
required: true
13+
type: string
14+
15+
jobs:
16+
build-docker:
17+
name: Build Docker Image
18+
uses: ./.github/workflows/docker-build.yml
19+
permissions:
20+
contents: read
21+
packages: write
22+
id-token: write
23+
secrets: inherit
24+
25+
create-release:
26+
name: Create GitHub Release
27+
runs-on: ubuntu-latest
28+
needs: build-docker
29+
permissions:
30+
contents: write
31+
32+
steps:
33+
- name: Checkout code
34+
uses: actions/checkout@v4
35+
with:
36+
fetch-depth: 0
37+
38+
- name: Get version from tag
39+
id: get_version
40+
run: |
41+
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
42+
VERSION="${{ inputs.tag }}"
43+
else
44+
VERSION=${GITHUB_REF#refs/tags/}
45+
fi
46+
echo "version=$VERSION" >> $GITHUB_OUTPUT
47+
echo "Version: $VERSION"
48+
49+
- name: Generate changelog
50+
id: changelog
51+
run: |
52+
# Get the previous tag
53+
PREV_TAG=$(git tag --sort=-v:refname | grep -E '^v?[0-9]+\.[0-9]+\.[0-9]+$' | sed -n '2p')
54+
55+
if [ -z "$PREV_TAG" ]; then
56+
echo "No previous tag found, using all commits"
57+
PREV_TAG=$(git rev-list --max-parents=0 HEAD)
58+
fi
59+
60+
echo "## What's Changed" > changelog.md
61+
echo "" >> changelog.md
62+
63+
# Generate commit log
64+
git log ${PREV_TAG}..HEAD --pretty=format:"* %s (%h)" --no-merges >> changelog.md
65+
66+
echo "" >> changelog.md
67+
echo "" >> changelog.md
68+
echo "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${PREV_TAG}...${{ steps.get_version.outputs.version }}" >> changelog.md
69+
70+
cat changelog.md
71+
72+
- name: Create Release
73+
uses: actions/github-script@v7
74+
with:
75+
github-token: ${{ secrets.GITHUB_TOKEN }}
76+
script: |
77+
const fs = require('fs');
78+
const changelog = fs.readFileSync('changelog.md', 'utf8');
79+
80+
const release = await github.rest.repos.createRelease({
81+
owner: context.repo.owner,
82+
repo: context.repo.repo,
83+
tag_name: '${{ steps.get_version.outputs.version }}',
84+
name: 'Release ${{ steps.get_version.outputs.version }}',
85+
body: changelog,
86+
draft: false,
87+
prerelease: false,
88+
make_latest: 'true'
89+
});
90+
91+
console.log(`Created release ${release.data.html_url}`);
92+
93+
// Add Docker image information to release
94+
const dockerImage = `ghcr.io/${{ github.repository }}:${{ steps.get_version.outputs.version }}`;
95+
await github.rest.repos.updateRelease({
96+
owner: context.repo.owner,
97+
repo: context.repo.repo,
98+
release_id: release.data.id,
99+
body: changelog + `\n\n## Docker Image\n\n\`\`\`bash\ndocker pull ${dockerImage}\n\`\`\``
100+
});

Dockerfile

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,27 @@ RUN apt-get update && apt-get install -y netcat-openbsd git make python3-dev lib
3939
COPY --from=builder /opt/venv /opt/venv
4040
# Copy requirements file
4141
COPY --from=builder /pulp_manager/requirements.txt ./
42-
# Copy the entire project
43-
COPY . .
42+
43+
# Copy application code
44+
COPY pulp_manager ./pulp_manager/
45+
COPY pulp3_bindings ./pulp3_bindings/
46+
COPY hashi_vault_client ./hashi_vault_client/
47+
48+
# Copy database migration files
49+
COPY alembic ./alembic/
50+
COPY alembic.ini ./
51+
52+
# Copy entrypoint script
53+
COPY pulp-manager.sh ./
54+
55+
# Install default configs to /etc/pulp_manager/
56+
RUN mkdir -p /etc/pulp_manager
57+
COPY config-examples/config.ini /etc/pulp_manager/config.ini
58+
COPY config-examples/pulp_config.yml /etc/pulp_manager/pulp_config.yml
4459

4560
# Ensure correct permissions
4661
RUN chown -R pulp_manager:pulp_manager /pulp_manager \
62+
&& chown -R pulp_manager:pulp_manager /etc/pulp_manager \
4763
&& ln -s /pulp_manager/pulp-manager.sh /usr/local/bin/pulp-manager
4864

4965
USER 10001

config-examples/README.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Configuration Examples
2+
3+
This directory contains example configuration files that are copied into the Docker image at `/etc/pulp_manager/`.
4+
5+
## Files
6+
7+
- `config.ini` - Main application configuration
8+
- `pulp_config.yml` - Pulp server and sync schedule configuration
9+
10+
## Usage
11+
12+
### Docker Image Default Configs
13+
14+
These configs are automatically copied to `/etc/pulp_manager/` during image build and serve as working defaults for testing and CI.
15+
16+
### Production Deployment
17+
18+
For production use, you have two options:
19+
20+
#### Option 1: Mount custom configs at the default location
21+
22+
```bash
23+
docker run -v /path/to/your/config.ini:/etc/pulp_manager/config.ini \
24+
-v /path/to/your/pulp_config.yml:/etc/pulp_manager/pulp_config.yml \
25+
pulp/pulp-manager
26+
```
27+
28+
#### Option 2: Mount configs anywhere and use environment variables
29+
30+
```bash
31+
docker run -v /path/to/configs:/configs \
32+
-e PULP_MANAGER_CONFIG_PATH=/configs/my-config.ini \
33+
-e PULP_SYNC_CONFIG_PATH=/configs/my-pulp-config.yml \
34+
pulp/pulp-manager
35+
```
36+
37+
### Environment Variable Overrides
38+
39+
The default `config.ini` supports environment variable substitution for common settings:
40+
41+
- `DB_HOSTNAME` - Database host (default: localhost)
42+
- `DB_PORT` - Database port (default: 3306)
43+
- `DB_NAME` - Database name (default: pulp_manager)
44+
- `DB_USER` - Database user (default: pulp-manager)
45+
- `DB_PASSWORD` - Database password (default: pulp-manager)
46+
- `REDIS_HOST` - Redis host (default: localhost)
47+
- `REDIS_PORT` - Redis port (default: 6379)
48+
- `REDIS_DB` - Redis database number (default: 0)
49+
- `PULP_ADMIN_PASSWORD` - Pulp admin password (default: password)
50+
51+
Example using environment variables:
52+
53+
```bash
54+
docker run -e DB_HOSTNAME=mysql.example.com \
55+
-e DB_PASSWORD=secret \
56+
-e REDIS_HOST=redis.example.com \
57+
pulp/pulp-manager
58+
```
59+
60+
## Configuration Locations
61+
62+
The application looks for configs in this order:
63+
64+
1. Environment variable `PULP_MANAGER_CONFIG_PATH` (if set)
65+
2. Default location `/etc/pulp_manager/config.ini`
66+
67+
And for Pulp sync config:
68+
69+
1. Environment variable `PULP_SYNC_CONFIG_PATH` (if set)
70+
2. Default location `/etc/pulp_manager/pulp_config.yml`

0 commit comments

Comments
 (0)