berg-iceberg 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- berg_iceberg-1.0.0/.github/CODEOWNERS +8 -0
- berg_iceberg-1.0.0/.github/ISSUE_TEMPLATE/bug_report.yml +26 -0
- berg_iceberg-1.0.0/.github/ISSUE_TEMPLATE/feature_request.yml +19 -0
- berg_iceberg-1.0.0/.github/dependabot.yml +12 -0
- berg_iceberg-1.0.0/.github/pull_request_template.md +16 -0
- berg_iceberg-1.0.0/.github/workflows/ci.yml +51 -0
- berg_iceberg-1.0.0/.github/workflows/codeql.yml +29 -0
- berg_iceberg-1.0.0/.github/workflows/release.yml +70 -0
- berg_iceberg-1.0.0/.github/workflows/spec-policy.yml +72 -0
- berg_iceberg-1.0.0/.gitignore +20 -0
- berg_iceberg-1.0.0/.python-version +2 -0
- berg_iceberg-1.0.0/Berg /342/200/224 Product Vision, Architecture, and Initial Engineering Specification.md" +2957 -0
- berg_iceberg-1.0.0/CAPABILITIES.md +382 -0
- berg_iceberg-1.0.0/Dockerfile.agent +13 -0
- berg_iceberg-1.0.0/ENGINEERING.md +1850 -0
- berg_iceberg-1.0.0/Makefile +55 -0
- berg_iceberg-1.0.0/PKG-INFO +67 -0
- berg_iceberg-1.0.0/README.md +52 -0
- berg_iceberg-1.0.0/SECURITY.md +11 -0
- berg_iceberg-1.0.0/V0_SCOPE.md +97 -0
- berg_iceberg-1.0.0/V1_SCOPE.md +173 -0
- berg_iceberg-1.0.0/berg.glue.yaml +17 -0
- berg_iceberg-1.0.0/berg.hive.yaml +13 -0
- berg_iceberg-1.0.0/berg.jdbc.yaml +19 -0
- berg_iceberg-1.0.0/berg.nessie.yaml +14 -0
- berg_iceberg-1.0.0/berg.polaris.yaml +18 -0
- berg_iceberg-1.0.0/berg.yaml +16 -0
- berg_iceberg-1.0.0/berg.yaml.example +16 -0
- berg_iceberg-1.0.0/docker-compose.agent.yml +32 -0
- berg_iceberg-1.0.0/docker-compose.hive.yml +55 -0
- berg_iceberg-1.0.0/docker-compose.jdbc.yml +49 -0
- berg_iceberg-1.0.0/docker-compose.nessie-maintenance.yml +9 -0
- berg_iceberg-1.0.0/docker-compose.nessie-native-maintenance.yml +17 -0
- berg_iceberg-1.0.0/docker-compose.nessie.yml +26 -0
- berg_iceberg-1.0.0/docker-compose.polaris.yml +101 -0
- berg_iceberg-1.0.0/docker-compose.rest-rustfs.yml +57 -0
- berg_iceberg-1.0.0/docker-compose.yml +57 -0
- berg_iceberg-1.0.0/docs/architecture.md +97 -0
- berg_iceberg-1.0.0/docs/aws-glue.md +75 -0
- berg_iceberg-1.0.0/docs/capabilities.md +18 -0
- berg_iceberg-1.0.0/docs/compatibility-matrix.md +41 -0
- berg_iceberg-1.0.0/docs/concepts.md +67 -0
- berg_iceberg-1.0.0/docs/local-development.md +208 -0
- berg_iceberg-1.0.0/docs/local-stress-test-report.md +65 -0
- berg_iceberg-1.0.0/docs/nessie-maintenance.md +29 -0
- berg_iceberg-1.0.0/docs/python-api.md +38 -0
- berg_iceberg-1.0.0/docs/roadmap.md +23 -0
- berg_iceberg-1.0.0/docs/security.md +66 -0
- berg_iceberg-1.0.0/examples/analytics-events.yaml +22 -0
- berg_iceberg-1.0.0/examples/local_iceberg/README.md +13 -0
- berg_iceberg-1.0.0/nessie-maintenance/pom.xml +57 -0
- berg_iceberg-1.0.0/nessie-maintenance/src/main/java/dev/berg/nessie/NessieSnapshotExpiration.java +99 -0
- berg_iceberg-1.0.0/pyproject.toml +47 -0
- berg_iceberg-1.0.0/scripts/__init__.py +1 -0
- berg_iceberg-1.0.0/scripts/create_fixtures.py +124 -0
- berg_iceberg-1.0.0/scripts/create_nessie_worker_fixture.py +26 -0
- berg_iceberg-1.0.0/scripts/nessie_expire_snapshots.sh +31 -0
- berg_iceberg-1.0.0/scripts/nessie_native_expire_snapshots.sh +46 -0
- berg_iceberg-1.0.0/scripts/verify_local.py +103 -0
- berg_iceberg-1.0.0/scripts/verify_snapshot_expiration.py +100 -0
- berg_iceberg-1.0.0/src/berg/__init__.py +3 -0
- berg_iceberg-1.0.0/src/berg/adapters/__init__.py +1 -0
- berg_iceberg-1.0.0/src/berg/adapters/iceberg/__init__.py +1 -0
- berg_iceberg-1.0.0/src/berg/adapters/iceberg/adapter.py +616 -0
- berg_iceberg-1.0.0/src/berg/cli/__init__.py +1 -0
- berg_iceberg-1.0.0/src/berg/cli/app.py +573 -0
- berg_iceberg-1.0.0/src/berg/config.py +113 -0
- berg_iceberg-1.0.0/src/berg/core/__init__.py +1 -0
- berg_iceberg-1.0.0/src/berg/core/audit.py +17 -0
- berg_iceberg-1.0.0/src/berg/core/desired.py +116 -0
- berg_iceberg-1.0.0/src/berg/core/errors.py +62 -0
- berg_iceberg-1.0.0/src/berg/core/execution.py +569 -0
- berg_iceberg-1.0.0/src/berg/core/handlers.py +145 -0
- berg_iceberg-1.0.0/src/berg/core/health.py +160 -0
- berg_iceberg-1.0.0/src/berg/core/models.py +315 -0
- berg_iceberg-1.0.0/src/berg/core/planning.py +123 -0
- berg_iceberg-1.0.0/src/berg/core/policy.py +45 -0
- berg_iceberg-1.0.0/src/berg/core/ports.py +100 -0
- berg_iceberg-1.0.0/src/berg/core/retention.py +77 -0
- berg_iceberg-1.0.0/src/berg/core/services.py +303 -0
- berg_iceberg-1.0.0/src/berg/sdk/__init__.py +5 -0
- berg_iceberg-1.0.0/src/berg/sdk/table.py +159 -0
- berg_iceberg-1.0.0/tests/__init__.py +0 -0
- berg_iceberg-1.0.0/tests/integration/__init__.py +0 -0
- berg_iceberg-1.0.0/tests/integration/catalog_contract.py +129 -0
- berg_iceberg-1.0.0/tests/integration/test_glue_catalog.py +34 -0
- berg_iceberg-1.0.0/tests/integration/test_hive_catalog.py +60 -0
- berg_iceberg-1.0.0/tests/integration/test_jdbc_catalog.py +29 -0
- berg_iceberg-1.0.0/tests/integration/test_local_catalog.py +120 -0
- berg_iceberg-1.0.0/tests/integration/test_nessie_catalog.py +55 -0
- berg_iceberg-1.0.0/tests/integration/test_network_interruption.py +105 -0
- berg_iceberg-1.0.0/tests/integration/test_polaris_catalog.py +24 -0
- berg_iceberg-1.0.0/tests/integration/test_postgres_execution.py +191 -0
- berg_iceberg-1.0.0/tests/stress/test_scalability.py +51 -0
- berg_iceberg-1.0.0/tests/unit/test_adapter.py +285 -0
- berg_iceberg-1.0.0/tests/unit/test_capabilities.py +30 -0
- berg_iceberg-1.0.0/tests/unit/test_cli.py +238 -0
- berg_iceberg-1.0.0/tests/unit/test_config.py +53 -0
- berg_iceberg-1.0.0/tests/unit/test_desired.py +188 -0
- berg_iceberg-1.0.0/tests/unit/test_errors.py +16 -0
- berg_iceberg-1.0.0/tests/unit/test_execution.py +479 -0
- berg_iceberg-1.0.0/tests/unit/test_health.py +80 -0
- berg_iceberg-1.0.0/tests/unit/test_models.py +15 -0
- berg_iceberg-1.0.0/tests/unit/test_plan_capabilities.py +82 -0
- berg_iceberg-1.0.0/tests/unit/test_planning.py +54 -0
- berg_iceberg-1.0.0/tests/unit/test_policy_audit.py +61 -0
- berg_iceberg-1.0.0/tests/unit/test_retention.py +302 -0
- berg_iceberg-1.0.0/tests/unit/test_sdk.py +54 -0
- berg_iceberg-1.0.0/uv.lock +1628 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Default ownership for repository changes.
|
|
2
|
+
* @NikosBakalis
|
|
3
|
+
|
|
4
|
+
# Changes to execution, authorization, and release controls require explicit
|
|
5
|
+
# review from the repository owner.
|
|
6
|
+
/src/berg/core/ @NikosBakalis
|
|
7
|
+
/.github/ @NikosBakalis
|
|
8
|
+
/Dockerfile* @NikosBakalis
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Report a reproducible problem in Berg
|
|
3
|
+
title: "[Bug]: "
|
|
4
|
+
labels: [bug]
|
|
5
|
+
body:
|
|
6
|
+
- type: textarea
|
|
7
|
+
id: description
|
|
8
|
+
attributes:
|
|
9
|
+
label: What happened?
|
|
10
|
+
description: Describe the observed and expected behavior.
|
|
11
|
+
validations:
|
|
12
|
+
required: true
|
|
13
|
+
- type: input
|
|
14
|
+
id: version
|
|
15
|
+
attributes:
|
|
16
|
+
label: Berg version
|
|
17
|
+
placeholder: v1.0.0
|
|
18
|
+
validations:
|
|
19
|
+
required: true
|
|
20
|
+
- type: textarea
|
|
21
|
+
id: reproduction
|
|
22
|
+
attributes:
|
|
23
|
+
label: Reproduction steps
|
|
24
|
+
description: Include commands, configuration, and sanitized logs.
|
|
25
|
+
validations:
|
|
26
|
+
required: true
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Propose a change to Berg
|
|
3
|
+
title: "[Feature]: "
|
|
4
|
+
labels: [enhancement]
|
|
5
|
+
body:
|
|
6
|
+
- type: textarea
|
|
7
|
+
id: problem
|
|
8
|
+
attributes:
|
|
9
|
+
label: Problem to solve
|
|
10
|
+
description: Explain the user or operational problem.
|
|
11
|
+
validations:
|
|
12
|
+
required: true
|
|
13
|
+
- type: textarea
|
|
14
|
+
id: proposal
|
|
15
|
+
attributes:
|
|
16
|
+
label: Proposed behavior
|
|
17
|
+
description: Describe desired behavior and safety constraints.
|
|
18
|
+
validations:
|
|
19
|
+
required: true
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
Describe the change and the user problem it solves.
|
|
4
|
+
|
|
5
|
+
## Safety and compatibility
|
|
6
|
+
|
|
7
|
+
- [ ] Plan, approval, idempotency, audit, and capability contracts are preserved.
|
|
8
|
+
- [ ] Unsupported backend behavior is rejected before mutation.
|
|
9
|
+
- [ ] Documentation and `ENGINEERING.md` were updated when appropriate.
|
|
10
|
+
|
|
11
|
+
## Verification
|
|
12
|
+
|
|
13
|
+
- [ ] `uv run ruff check .`
|
|
14
|
+
- [ ] `uv run mypy src`
|
|
15
|
+
- [ ] `uv run pytest -W error::ResourceWarning`
|
|
16
|
+
- [ ] Relevant Docker or integration tests were run.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
quality:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- name: Check out repository
|
|
15
|
+
uses: actions/checkout@v7
|
|
16
|
+
|
|
17
|
+
- name: Install uv
|
|
18
|
+
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
|
19
|
+
with:
|
|
20
|
+
enable-cache: true
|
|
21
|
+
|
|
22
|
+
- name: Set up Python
|
|
23
|
+
run: uv python install 3.13
|
|
24
|
+
|
|
25
|
+
- name: Install dependencies
|
|
26
|
+
run: uv sync --locked --group dev
|
|
27
|
+
|
|
28
|
+
- name: Run lint
|
|
29
|
+
run: uv run ruff check .
|
|
30
|
+
|
|
31
|
+
- name: Run type checks
|
|
32
|
+
run: uv run mypy src
|
|
33
|
+
|
|
34
|
+
- name: Run tests
|
|
35
|
+
run: uv run pytest -W error::ResourceWarning
|
|
36
|
+
|
|
37
|
+
- name: Validate Compose files
|
|
38
|
+
env:
|
|
39
|
+
BERG_MINIO_USER: ci-local
|
|
40
|
+
BERG_MINIO_PASSWORD: ci-local-password-that-is-long-enough
|
|
41
|
+
run: |
|
|
42
|
+
docker compose -f docker-compose.yml config >/dev/null
|
|
43
|
+
docker compose -f docker-compose.rest-rustfs.yml config >/dev/null
|
|
44
|
+
docker compose -f docker-compose.nessie.yml config >/dev/null
|
|
45
|
+
docker compose -f docker-compose.nessie-maintenance.yml config >/dev/null
|
|
46
|
+
docker compose -f docker-compose.nessie-native-maintenance.yml config >/dev/null
|
|
47
|
+
docker compose -f docker-compose.polaris.yml config >/dev/null
|
|
48
|
+
docker compose -f docker-compose.jdbc.yml config >/dev/null
|
|
49
|
+
docker compose -f docker-compose.hive.yml config >/dev/null
|
|
50
|
+
BERG_AGENT_CONFIG=/tmp/berg.yaml BERG_AGENT_PLAN=/tmp/plan.json \
|
|
51
|
+
docker compose -f docker-compose.agent.yml config >/dev/null
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: CodeQL
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
schedule:
|
|
9
|
+
- cron: '23 3 * * 1'
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
security-events: write
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
analyze:
|
|
17
|
+
name: Analyze Python
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
steps:
|
|
20
|
+
- name: Check out repository
|
|
21
|
+
uses: actions/checkout@v7
|
|
22
|
+
- name: Initialize CodeQL
|
|
23
|
+
uses: github/codeql-action/init@v3
|
|
24
|
+
with:
|
|
25
|
+
languages: python
|
|
26
|
+
- name: Perform CodeQL analysis
|
|
27
|
+
uses: github/codeql-action/analyze@v3
|
|
28
|
+
with:
|
|
29
|
+
category: /language:python
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
name: Berg release artifacts
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
packages: write
|
|
12
|
+
id-token: write
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
artifacts:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- name: Check out repository
|
|
19
|
+
uses: actions/checkout@v7
|
|
20
|
+
|
|
21
|
+
- name: Install uv
|
|
22
|
+
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
|
23
|
+
with:
|
|
24
|
+
enable-cache: true
|
|
25
|
+
|
|
26
|
+
- name: Set up Python
|
|
27
|
+
run: uv python install 3.13
|
|
28
|
+
|
|
29
|
+
- name: Build Python distributions
|
|
30
|
+
run: uv build
|
|
31
|
+
|
|
32
|
+
- name: Build Agent image
|
|
33
|
+
run: docker build --file Dockerfile.agent --tag berg-agent:${GITHUB_SHA} .
|
|
34
|
+
|
|
35
|
+
- name: Upload Python distributions
|
|
36
|
+
uses: actions/upload-artifact@v4
|
|
37
|
+
with:
|
|
38
|
+
name: berg-python-${{ github.sha }}
|
|
39
|
+
path: dist/
|
|
40
|
+
|
|
41
|
+
- name: Export Agent image artifact
|
|
42
|
+
run: docker save berg-agent:${GITHUB_SHA} --output berg-agent-${GITHUB_SHA}.tar
|
|
43
|
+
|
|
44
|
+
- name: Upload Agent image
|
|
45
|
+
uses: actions/upload-artifact@v4
|
|
46
|
+
with:
|
|
47
|
+
name: berg-agent-${{ github.sha }}
|
|
48
|
+
path: berg-agent-${{ github.sha }}.tar
|
|
49
|
+
|
|
50
|
+
- name: Log in to GitHub Container Registry
|
|
51
|
+
uses: docker/login-action@v3
|
|
52
|
+
with:
|
|
53
|
+
registry: ghcr.io
|
|
54
|
+
username: ${{ github.actor }}
|
|
55
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
56
|
+
|
|
57
|
+
- name: Publish Agent image
|
|
58
|
+
env:
|
|
59
|
+
IMAGE_NAME: ghcr.io/berg-cloud/berg-agent
|
|
60
|
+
run: |
|
|
61
|
+
docker tag berg-agent:${GITHUB_SHA} "${IMAGE_NAME}:${GITHUB_REF_NAME}"
|
|
62
|
+
docker tag berg-agent:${GITHUB_SHA} "${IMAGE_NAME}:latest"
|
|
63
|
+
docker push "${IMAGE_NAME}:${GITHUB_REF_NAME}"
|
|
64
|
+
docker push "${IMAGE_NAME}:latest"
|
|
65
|
+
|
|
66
|
+
- name: Publish Python distributions to PyPI
|
|
67
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
68
|
+
with:
|
|
69
|
+
packages-dir: dist/
|
|
70
|
+
password: ${{ secrets.PYPI_API_TOKEN }}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
name: Berg specification policy
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
paths:
|
|
6
|
+
- "**/*.yaml"
|
|
7
|
+
- "**/*.yml"
|
|
8
|
+
- "**/*.json"
|
|
9
|
+
- "src/berg/core/**"
|
|
10
|
+
- "src/berg/sdk/**"
|
|
11
|
+
- "tests/unit/test_policy_audit.py"
|
|
12
|
+
- "tests/unit/test_sdk.py"
|
|
13
|
+
- ".github/workflows/spec-policy.yml"
|
|
14
|
+
workflow_dispatch:
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: read
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
validate:
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
steps:
|
|
23
|
+
- name: Check out repository
|
|
24
|
+
uses: actions/checkout@v7
|
|
25
|
+
|
|
26
|
+
- name: Install uv
|
|
27
|
+
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
|
28
|
+
with:
|
|
29
|
+
enable-cache: true
|
|
30
|
+
|
|
31
|
+
- name: Set up Python
|
|
32
|
+
run: uv python install 3.13
|
|
33
|
+
|
|
34
|
+
- name: Install dependencies
|
|
35
|
+
run: uv sync --locked --group dev
|
|
36
|
+
|
|
37
|
+
- name: Validate canonical specifications
|
|
38
|
+
run: uv run berg validate-spec examples/analytics-events.yaml --output json
|
|
39
|
+
|
|
40
|
+
- name: Start disposable catalog for plan generation
|
|
41
|
+
env:
|
|
42
|
+
BERG_MINIO_USER: ci-local
|
|
43
|
+
BERG_MINIO_PASSWORD: ci-local-password-that-is-long-enough
|
|
44
|
+
run: docker compose up -d --wait
|
|
45
|
+
|
|
46
|
+
- name: Create disposable desired-state fixture
|
|
47
|
+
env:
|
|
48
|
+
AWS_ACCESS_KEY_ID: ci-local
|
|
49
|
+
AWS_SECRET_ACCESS_KEY: ci-local-password-that-is-long-enough
|
|
50
|
+
run: uv run python scripts/create_fixtures.py --stage healthy --table-name events
|
|
51
|
+
|
|
52
|
+
- name: Generate machine-readable pull-request plan
|
|
53
|
+
env:
|
|
54
|
+
AWS_ACCESS_KEY_ID: ci-local
|
|
55
|
+
AWS_SECRET_ACCESS_KEY: ci-local-password-that-is-long-enough
|
|
56
|
+
run: uv run berg plan --spec examples/analytics-events.yaml --output json --save policy-plan.json
|
|
57
|
+
|
|
58
|
+
- name: Publish plan artifact
|
|
59
|
+
uses: actions/upload-artifact@v4
|
|
60
|
+
with:
|
|
61
|
+
name: berg-policy-plan-${{ github.sha }}
|
|
62
|
+
path: policy-plan.json
|
|
63
|
+
|
|
64
|
+
- name: Run SDK and authorization policy contracts
|
|
65
|
+
run: uv run pytest tests/unit/test_sdk.py tests/unit/test_policy_audit.py -q
|
|
66
|
+
|
|
67
|
+
- name: Remove disposable catalog
|
|
68
|
+
if: always()
|
|
69
|
+
env:
|
|
70
|
+
BERG_MINIO_USER: ci-local
|
|
71
|
+
BERG_MINIO_PASSWORD: ci-local-password-that-is-long-enough
|
|
72
|
+
run: docker compose down --volumes --remove-orphans
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
.venv/
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
.pytest_cache/
|
|
5
|
+
.berg/
|
|
6
|
+
.ruff_cache/
|
|
7
|
+
.mypy_cache/
|
|
8
|
+
.aws/
|
|
9
|
+
.agents/
|
|
10
|
+
.codex/
|
|
11
|
+
dist/
|
|
12
|
+
**/target/
|
|
13
|
+
*.class
|
|
14
|
+
coverage.xml
|
|
15
|
+
htmlcov/
|
|
16
|
+
.coverage
|
|
17
|
+
.DS_Store
|
|
18
|
+
.env
|
|
19
|
+
.env.*
|
|
20
|
+
!.env.example
|