Skip to content

Commit b184977

Browse files
authored
feat(init): Initial commit of the Prometheus Toggl Track Exporter project (#1)
* Initial commit of the Prometheus Toggl Track Exporter project, including core functionality, Docker support, Helm chart for Kubernetes deployment, and CI/CD workflows. Added configuration files, environment setup, and basic metrics collection from the Toggl Track API. * Refactor exporter and test files for improved readability and consistency. Updated import order, enhanced error messages, and standardized assertion methods in tests. Adjusted function signatures and comments for clarity. Ensured metrics handling remains robust during API errors.
1 parent 1453df8 commit b184977

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+4008
-3
lines changed

.cursor/rules/default.mdc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
description:
3+
globs:
4+
alwaysApply: true
5+
---
6+
7+
- Use Poetry to manage deps in this project
8+
- Use ruff to format code
9+
- Use Task to run commands

.env.example

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Required
2+
TODOIST_API_TOKEN=your_todoist_api_token_here
3+
4+
# Optional with defaults
5+
EXPORTER_PORT=9090
6+
METRICS_PATH=/metrics
7+
COLLECTION_INTERVAL=60
8+
9+
# Completed tasks time windows
10+
COMPLETED_TASKS_DAYS=7
11+
COMPLETED_TASKS_HOURS=24

.github/workflows/ci.yml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- name: Checkout repository
14+
uses: actions/checkout@v4
15+
16+
- name: Cache asdf
17+
uses: actions/cache@v4
18+
id: asdf-cache
19+
with:
20+
path: ~/.asdf
21+
key: ${{ runner.os }}-asdf-${{ hashFiles('.tool-versions') }}
22+
restore-keys: |
23+
${{ runner.os }}-asdf-
24+
25+
- name: Cache Poetry
26+
uses: actions/cache@v4
27+
id: poetry-cache
28+
with:
29+
path: ~/.cache/pypoetry
30+
key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }}
31+
restore-keys: |
32+
${{ runner.os }}-poetry-
33+
34+
- name: Install asdf
35+
uses: asdf-vm/actions/install@1117842ea70e2711a0072e3a71265cbfe2c830be # v0.16
36+
37+
- name: Setup asdf plugins
38+
run: |
39+
asdf plugin add python
40+
asdf plugin add poetry
41+
asdf plugin add task
42+
43+
- name: Install tools with asdf
44+
run: |
45+
asdf install
46+
pip install poetry
47+
asdf reshim python
48+
49+
- name: Install dependencies
50+
run: task install
51+
52+
- name: Run linting
53+
run: task lint
54+
55+
- name: Run tests
56+
run: task test
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
name: Docker Build and Publish
2+
3+
on:
4+
workflow_run:
5+
workflows: ["Release Please"]
6+
types:
7+
- completed
8+
push:
9+
branches: [ main ]
10+
tags:
11+
- 'v*'
12+
pull_request:
13+
branches: [ main ]
14+
15+
env:
16+
REGISTRY: ghcr.io
17+
IMAGE_NAME: echohello-dev/prometheus-toggl-track-exporter
18+
19+
jobs:
20+
build:
21+
runs-on: ubuntu-latest
22+
permissions:
23+
contents: read
24+
packages: write
25+
outputs:
26+
is_release: ${{ steps.check-release.outputs.release_found }}
27+
release_tag: ${{ steps.check-release.outputs.release_tag }}
28+
29+
steps:
30+
- name: Checkout repository
31+
uses: actions/checkout@v4
32+
with:
33+
fetch-depth: 0
34+
35+
- name: Check for release
36+
id: check-release
37+
run: |
38+
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "no-tag")
39+
if [[ $LATEST_TAG =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
40+
echo "Found release tag: $LATEST_TAG"
41+
echo "release_found=true" >> $GITHUB_OUTPUT
42+
echo "release_tag=$LATEST_TAG" >> $GITHUB_OUTPUT
43+
else
44+
echo "No release tag found"
45+
echo "release_found=false" >> $GITHUB_OUTPUT
46+
fi
47+
48+
- name: Cache asdf
49+
uses: actions/cache@v4
50+
id: asdf-cache
51+
with:
52+
path: ~/.asdf
53+
key: ${{ runner.os }}-asdf-${{ hashFiles('.tool-versions') }}
54+
restore-keys: |
55+
${{ runner.os }}-asdf-
56+
57+
- name: Cache Poetry
58+
uses: actions/cache@v4
59+
id: poetry-cache
60+
with:
61+
path: ~/.cache/pypoetry
62+
key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }}
63+
restore-keys: |
64+
${{ runner.os }}-poetry-
65+
66+
- name: Install asdf
67+
uses: asdf-vm/actions/install@1117842ea70e2711a0072e3a71265cbfe2c830be # v0.16
68+
69+
- name: Setup asdf plugins
70+
run: |
71+
asdf plugin add python
72+
asdf plugin add poetry
73+
asdf plugin add task
74+
75+
- name: Install tools with asdf
76+
run: |
77+
asdf install
78+
pip install poetry
79+
asdf reshim python
80+
81+
- name: Install dependencies
82+
run: task install
83+
84+
- name: Log in to the Container registry
85+
uses: docker/login-action@v3
86+
with:
87+
registry: ${{ env.REGISTRY }}
88+
username: ${{ github.actor }}
89+
password: ${{ secrets.GITHUB_TOKEN }}
90+
91+
- name: Set up Docker Buildx
92+
uses: docker/setup-buildx-action@v3
93+
94+
- name: Extract metadata for Docker
95+
id: meta
96+
uses: docker/metadata-action@v5
97+
with:
98+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
99+
tags: |
100+
type=raw,value=latest,enable=${{ steps.check-release.outputs.release_found == 'true' }}
101+
type=raw,value=${{ steps.check-release.outputs.release_tag }},enable=${{ steps.check-release.outputs.release_found == 'true' }}
102+
type=ref,event=branch
103+
type=ref,event=pr
104+
type=semver,pattern={{version}}
105+
type=semver,pattern={{major}}.{{minor}}
106+
type=sha,format=long
107+
108+
- name: Build and push Docker image
109+
uses: docker/build-push-action@v6
110+
with:
111+
context: .
112+
push: ${{ github.event_name != 'pull_request' }}
113+
tags: ${{ steps.meta.outputs.tags }}
114+
labels: ${{ steps.meta.outputs.labels }}
115+
cache-from: type=gha
116+
cache-to: type=gha,mode=max

.github/workflows/publish-pypi.yml

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
name: Publish to PyPI
2+
3+
on:
4+
workflow_run:
5+
workflows: ["Release Please"]
6+
types:
7+
- completed
8+
push:
9+
tags:
10+
- 'v*'
11+
12+
jobs:
13+
publish-pypi:
14+
runs-on: ubuntu-latest
15+
if: ${{ github.event.workflow_run.conclusion == 'success' || github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
16+
steps:
17+
- name: Checkout repository
18+
uses: actions/checkout@v4
19+
with:
20+
ref: ${{ github.event_name == 'workflow_run' && 'main' || '' }}
21+
fetch-depth: 0
22+
23+
- name: Check for release
24+
id: check-release
25+
run: |
26+
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "no-tag")
27+
if [[ $LATEST_TAG =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
28+
echo "Found release tag: $LATEST_TAG"
29+
echo "release_found=true" >> $GITHUB_OUTPUT
30+
echo "release_tag=$LATEST_TAG" >> $GITHUB_OUTPUT
31+
else
32+
echo "No release tag found"
33+
echo "release_found=false" >> $GITHUB_OUTPUT
34+
fi
35+
36+
- name: Cache asdf
37+
if: steps.check-release.outputs.release_found == 'true'
38+
uses: actions/cache@v4
39+
id: asdf-cache
40+
with:
41+
path: ~/.asdf
42+
key: ${{ runner.os }}-asdf-${{ hashFiles('.tool-versions') }}
43+
restore-keys: |
44+
${{ runner.os }}-asdf-
45+
46+
- name: Cache Poetry
47+
if: steps.check-release.outputs.release_found == 'true'
48+
uses: actions/cache@v4
49+
id: poetry-cache
50+
with:
51+
path: ~/.cache/pypoetry
52+
key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }}
53+
restore-keys: |
54+
${{ runner.os }}-poetry-
55+
56+
- name: Install asdf
57+
if: steps.check-release.outputs.release_found == 'true'
58+
uses: asdf-vm/actions/install@1117842ea70e2711a0072e3a71265cbfe2c830be # v0.16
59+
60+
- name: Setup asdf plugins
61+
if: steps.check-release.outputs.release_found == 'true'
62+
run: |
63+
asdf plugin add python
64+
asdf plugin add poetry
65+
asdf plugin add task
66+
67+
- name: Install tools with asdf
68+
if: steps.check-release.outputs.release_found == 'true'
69+
run: |
70+
asdf install
71+
pip install poetry
72+
asdf reshim python
73+
74+
- name: Install dependencies
75+
if: steps.check-release.outputs.release_found == 'true'
76+
run: task install
77+
78+
- name: Build and publish to PyPI
79+
if: steps.check-release.outputs.release_found == 'true'
80+
env:
81+
POETRY_PYPI_TOKEN_PYPI: ${{ secrets.POETRY_PYPI_TOKEN_PYPI }}
82+
run: task publish-pypi
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: Release Please
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
8+
permissions:
9+
contents: write
10+
pull-requests: write
11+
12+
jobs:
13+
release-please:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- id: release
17+
uses: googleapis/release-please-action@v4
18+
with:
19+
token: ${{ secrets.GITHUB_TOKEN }}
20+
config-file: release-please-config.json
21+
manifest-file: .release-please-manifest.json

.gitignore

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
6+
# C extensions
7+
*.so
8+
9+
# Distribution / packaging
10+
.Python
11+
build/
12+
develop-eggs/
13+
dist/
14+
downloads/
15+
eggs/
16+
.eggs/
17+
lib/
18+
lib64/
19+
parts/
20+
sdist/
21+
var/
22+
wheels/
23+
*.egg-info/
24+
.installed.cfg
25+
*.egg
26+
27+
# Unit test / coverage reports
28+
htmlcov/
29+
.tox/
30+
.coverage
31+
.coverage.*
32+
.cache
33+
nosetests.xml
34+
coverage.xml
35+
*.cover
36+
.hypothesis/
37+
.pytest_cache/
38+
39+
# Environments
40+
.env
41+
.venv
42+
env/
43+
venv/
44+
ENV/
45+
env.bak/
46+
venv.bak/
47+
48+
# IDEs and editors
49+
.idea/
50+
*.swp
51+
*.swo
52+
53+
.DS_Store

.pre-commit-config.yaml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
repos:
2+
- repo: https://github.com/pre-commit/pre-commit-hooks
3+
rev: v5.0.0
4+
hooks:
5+
- id: trailing-whitespace
6+
- id: end-of-file-fixer
7+
- id: check-yaml
8+
exclude: ^deploy/helm/
9+
- id: check-added-large-files
10+
- id: check-toml
11+
- id: check-merge-conflict
12+
- id: debug-statements
13+
14+
- repo: https://github.com/charliermarsh/ruff-pre-commit
15+
rev: v0.11.2
16+
hooks:
17+
- id: ruff
18+
args: [--fix]
19+
- id: ruff-format
20+
21+
- repo: https://github.com/python-poetry/poetry
22+
rev: 2.1.2
23+
hooks:
24+
- id: poetry-check
25+
26+
- repo: local
27+
hooks:
28+
- id: pytest
29+
name: pytest
30+
entry: poetry run pytest
31+
language: system
32+
pass_filenames: false
33+
types: [python]

.release-please-manifest.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
".": "1.0.0"
3+
}

.tool-versions

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
python 3.13.2
2+
task 3.42.1

0 commit comments

Comments
 (0)