Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
name: CI/CD Pipeline

on:
push:
branches: [ main, develop, feature/* ]
pull_request:
branches: [ main, develop ]

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.9, 3.10, 3.11]

steps:
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt

- name: Lint with flake8
run: |
pip install flake8
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics

- name: Test with pytest
run: |
python -m pytest tests/ --cov=app --cov-report=xml --cov-report=term-missing

- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v3
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

build:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'

steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: 3.11

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt

- name: Build application
run: |
echo "Building application..."
# Add build steps here if needed

- name: Deploy to staging
run: |
echo "Deploying to staging environment..."
# Add deployment steps here
134 changes: 134 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
.python-version

# pipenv
Pipfile.lock

# PEP 582
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageM2ath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# VS Code
.vscode/

# macOS
.DS_Store

# Windows
Thumbs.db
ehthumbs.db
Desktop.ini
95 changes: 95 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
"""
ポモドーロタイマー Webアプリケーション
Flask + SocketIO + HTML/CSS/JavaScript で構築されたポモドーロタイマー
"""

from flask import Flask, render_template, jsonify, request
from flask_socketio import SocketIO, emit
import os

# Flask アプリケーションの初期化
app = Flask(__name__)
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', 'pomodoro-timer-secret-key-change-in-production')

# SocketIOの初期化
socketio = SocketIO(app, cors_allowed_origins="*")

@app.route('/')
def index():
"""メインページの表示"""
return render_template('index.html')

@app.route('/health')
def health():
"""ヘルスチェック用エンドポイント"""
return jsonify({
'status': 'healthy',
'message': 'ポモドーロタイマーアプリケーションが正常に動作しています'
})

@app.route('/api/settings', methods=['GET', 'POST'])
def handle_settings():
"""
設定の取得・保存API(将来の拡張用)
"""
if request.method == 'GET':
# デフォルト設定を返す
default_settings = {
'workDuration': 25,
'shortBreakDuration': 5,
'longBreakDuration': 15,
'sessionsUntilLongBreak': 4,
'autoStartBreaks': False,
'autoStartWork': False,
'soundNotifications': True
}
return jsonify(default_settings)

elif request.method == 'POST':
# 設定の保存(現在はクライアントサイドのみ)
settings = request.get_json()
# 実際のアプリケーションではデータベースに保存
return jsonify({
'status': 'success',
'message': '設定が保存されました'
})

# SocketIOイベントハンドラー(将来のリアルタイム機能用)
@socketio.on('connect')
def handle_connect():
"""クライアント接続時の処理"""
print('クライアントが接続されました')
emit('connected', {'message': 'サーバーに正常に接続されました'})

@socketio.on('disconnect')
def handle_disconnect():
"""クライアント切断時の処理"""
print('クライアントが切断されました')

@socketio.on('timer_state')
def handle_timer_state(data):
"""タイマー状態の同期(将来の拡張用)"""
# 他のクライアントに状態を配信(マルチユーザー機能用)
emit('timer_update', data, broadcast=True, include_self=False)

# エラーハンドラー
@app.errorhandler(404)
def not_found_error(error):
"""404エラーハンドラー"""
return render_template('index.html'), 404

@app.errorhandler(500)
def internal_error(error):
"""500エラーハンドラー"""
return jsonify({
'error': 'Internal server error',
'message': 'サーバー内部エラーが発生しました'
}), 500

if __name__ == '__main__':
# 開発環境での実行
socketio.run(app,
debug=True,
host='0.0.0.0',
port=5000,
allow_unsafe_werkzeug=True)
Loading