Skip to content
This repository was archived by the owner on Oct 22, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
63efa15
Port old into new
harismacic1 Nov 5, 2025
90c143c
#4766 Fix isLastColumn and isFirstColumn are null bug
harismacic1 Nov 6, 2025
03841e5
#4770 Make autosave on status change
harismacic1 Nov 6, 2025
620a17a
#4770 Add autosave on every section except on tags
harismacic1 Nov 6, 2025
6f822a6
#4770 Edit syntax error
harismacic1 Nov 6, 2025
9f21dcd
#4770 Make autosave on tag adding
harismacic1 Nov 7, 2025
4a0fdd5
#4770 Add event listener to make link element referencing possible
harismacic1 Nov 10, 2025
2d3969b
#4793 Make timesheet container scrollable
harismacic1 Nov 10, 2025
eecc7f7
#4793 Leave scrollbar not visible
harismacic1 Nov 11, 2025
cff28d6
#4793 Remove unused css
harismacic1 Nov 11, 2025
68595e8
#4793 Uninstall unused package
harismacic1 Nov 11, 2025
e6f9407
#4635 Fix time on multiple time logging
harismacic1 Nov 12, 2025
79d3cdb
#4815 Make All timesheets table scrollable
harismacic1 Nov 11, 2025
1ef3ce4
[#4836] Try to fix date in the table
harismacic1 Nov 13, 2025
2805c75
[#4836] Fix bug with time in multiple logs on the same ticket, use re…
harismacic1 Nov 13, 2025
fdd36b9
[#4836] Remove redudant conversion
harismacic1 Nov 13, 2025
fcc5540
#4836 Remove error logs
harismacic1 Nov 13, 2025
1eb6781
#4836 Format code
harismacic1 Nov 13, 2025
ead7a5b
#4836 Fix CD syntax
harismacic1 Nov 14, 2025
685188d
#4836 Final version of CD file
harismacic1 Nov 14, 2025
1808e73
#4841 Add ticket ID column to the All Timesheets
farukvukovic Nov 14, 2025
acc2491
#4794 Make ticket time logs editable
harismacic1 Nov 11, 2025
16fa266
#4794 Rename edit ticket title and delete unecessary labels
harismacic1 Nov 11, 2025
5853a48
#4784 Add button and clone ticket controller
harismacic1 Nov 12, 2025
638a69c
#4784 Navigate to kanban after ticket cloning, add notification for c…
harismacic1 Nov 12, 2025
8592ace
#4784 Add notification message
harismacic1 Nov 12, 2025
72eeb84
#4784 Extract Clone To-Do button to options
harismacic1 Nov 14, 2025
b0ebb70
#4784 Change ticket details css
harismacic1 Nov 14, 2025
0f3293b
#4771 Fix the Leantimes session issue
farukvukovic Nov 17, 2025
a410d43
#4700 fix All Projects UI
farukvukovic Nov 18, 2025
87dedf4
#4785 Add multiple filtering options to kanban board
farukvukovic Nov 11, 2025
0dcb21e
#4785 Comment legacy kanban search code instead of deleting it
farukvukovic Nov 17, 2025
5ab3812
#4785 Remove console.log statements
farukvukovic Nov 17, 2025
2b9f975
#4775 Add search functionality to all timesheets page
farukvukovic Nov 20, 2025
2041f72
#4775 Restore idea, plugins submodule, and build artifacts
farukvukovic Nov 19, 2025
5f0c2ec
#4775 Fix Tick.ID filtering and disable difference column search
farukvukovic Nov 19, 2025
634c15f
#4898 Fix issue with logging time on wrong date
harismacic1 Nov 18, 2025
cd8c0ac
#4784 Address QA comments, make every tickets detail being cloned
harismacic1 Nov 20, 2025
d73275c
Revert "#4784 Address QA comments, make every tickets detail being cl…
harismacic1 Nov 20, 2025
b975901
#4784 Address QA comments, make every tickets detail being cloned
harismacic1 Nov 20, 2025
00ee5c2
#4784 Address PR issues, remove error log
harismacic1 Nov 20, 2025
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
53 changes: 43 additions & 10 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,50 @@
### Description
# Description

*Please include a short description of the suggested change and the reasoning behind the approach you have chosen.*
<!--- Provide a general summary of the changes in the Title above -->
Preview link:

### Link to ticket
Resolves [](https://leantime.pearshadow.com/tickets)

*Please add a link to the GitHub issue being addressed by this change.*

### Type
# Screenshots

- [ ] Fix
- [ ] Feature
- [ ] Cleanup
Please make sure to include both desktop and mobile screenshots.

### Screenshot of the result
### Before

*If your change affects the user interface, you should include a screenshot of the result with the pull request.*
<table style="width: 100%;">
<tr>
<th>Desktop</th>
<th>Mobile</th>
</tr>
<tr>
<td>SCREENSHOT</td>
<td>SCREENSHOT</td>
</tr>
</table>

### After

<table style="width: 100%;">
<tr>
<th>Desktop</th>
<th>Mobile</th>
</tr>
<tr>
<td>SCREENSHOT</td>
<td>SCREENSHOT</td>
</tr>
</table>

### Figma

<table style="width: 100%;">
<tr>
<th>Desktop</th>
<th>Mobile</th>
</tr>
<tr>
<td>SCREENSHOT</td>
<td>SCREENSHOT</td>
</tr>
</table>
73 changes: 73 additions & 0 deletions .github/SECRETS-SETUP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# GitHub Secrets - Quick Setup

## Required Secrets

Go to: **Settings → Secrets and variables → Actions → New repository secret**

> **Note:** Replace all placeholder values below (e.g., `your.server.ip.address`, `your-ssh-username`) with your actual server configuration values.

---

### 1. SSH_PRIVATE_KEY

```bash
# Display key content:
cat ~/.ssh/your-private-key
```

Copy the **entire output** (including `-----BEGIN ... KEY-----` and `-----END ... KEY-----`) and paste into GitHub Secret.

---

### 2. SSH_HOST

**Value:** `your.server.ip.address`

---

### 3. SSH_USER

**Value:** `your-ssh-username`

---

### 4. STAGING_PATH

**Value:** `your-leantime-staging-path`

---

### 5. PRODUCTION_PATH

**Value:** `your-leantime-production-path`

---

### 6. PRODUCTION_URL (optional)

**Value:** `https://your-production-domain.com`

Replace with your actual production application URL for health checks.

---

## Verification

After adding all secrets, you should see:

```
✓ SSH_PRIVATE_KEY
✓ SSH_HOST
✓ SSH_USER
✓ STAGING_PATH
✓ PRODUCTION_PATH
✓ PRODUCTION_URL
```

## Testing

1. Ensure develop branch exists: `git checkout develop`
2. Push: `git push -u origin develop`
3. GitHub Actions will automatically start deployment
4. Monitor in **Actions** tab

225 changes: 225 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
name: Deploy Leantime

on:
push:
branches:
- develop
- master
workflow_dispatch:

jobs:
deploy:
name: Deploy to Server
runs-on: ubuntu-latest

steps:
- name: Setup SSH
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
SSH_HOST: ${{ secrets.SSH_HOST }}
run: |
mkdir -p ~/.ssh
echo "$SSH_PRIVATE_KEY" > ~/.ssh/deploy_key
chmod 600 ~/.ssh/deploy_key
ssh-keyscan -H $SSH_HOST >> ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts

- name: Deploy to Staging
if: github.ref == 'refs/heads/develop'
env:
SSH_HOST: ${{ secrets.SSH_HOST }}
SSH_USER: ${{ secrets.SSH_USER }}
STAGING_PATH: ${{ secrets.STAGING_PATH }}
STAGING_ENV_FILE: ${{ secrets.STAGING_ENV_FILE }}
run: |
echo "Deploying to STAGING"

# Deploy using git pull on server
ssh -i ~/.ssh/deploy_key -o StrictHostKeyChecking=no $SSH_USER@$SSH_HOST << ENDSSH
set -e # Exit on error

echo "Changing to deployment directory..."
cd $STAGING_PATH

echo "Fetching latest changes..."
git fetch origin develop

echo "Creating backup tag..."
BACKUP_TAG="backup-staging-$(date +%Y%m%d_%H%M%S)"
git tag -f $BACKUP_TAG HEAD
echo "Backup tag created: $BACKUP_TAG"

echo "Pulling latest code from develop branch..."
git pull origin develop

echo "Installing Composer dependencies..."
composer install --no-dev --optimize-autoloader --no-interaction

echo "Installing NPM dependencies..."
npm ci

echo "Building frontend assets..."
npx mix --production

echo "Generating blocklist..."
node generateBlocklist.mjs

echo "Clearing cache..."
# Clear cache files
sudo find bootstrap/cache -type f ! -name '.gitignore' -delete 2>/dev/null || true
sudo find storage/framework/cache -type f ! -name '.gitignore' -delete 2>/dev/null || true
sudo find storage/framework/sessions -type f ! -name '.gitignore' -delete 2>/dev/null || true
sudo find storage/framework/views -type f ! -name '.gitignore' -delete 2>/dev/null || true

echo "Setting proper file permissions..."
# Set ownership for application files
sudo chown -R www-data:www-data $STAGING_PATH

# Secure .env file permissions
sudo chmod 600 config/.env 2>/dev/null || true

# Make writable directories
sudo chmod -R 775 storage bootstrap/cache userfiles public/userfiles 2>/dev/null || true

echo "Reloading services..."
# Reload PHP-FPM to clear opcache
sudo systemctl reload php8.2-fpm

# Reload nginx
sudo systemctl reload nginx

echo "Staging deployment completed successfully!"
echo "Commit: $(git rev-parse --short HEAD)"
echo "Rollback available: git reset --hard $BACKUP_TAG"
ENDSSH

- name: Health Check Staging
if: github.ref == 'refs/heads/develop'
env:
STAGING_URL: ${{ secrets.STAGING_URL }}
run: |
echo " Running staging health check..."
sleep 3

response=$(curl -s -o /dev/null -w "%{http_code}" $STAGING_URL/healthCheck.php 2>/dev/null || echo "000")

if [ "$response" = "200" ]; then
echo " Staging health check passed! (HTTP $response)"
else
echo " Warning: Health check returned HTTP $response"
echo "Please verify the staging deployment manually at $STAGING_URL"
fi

- name: Deploy to Production
if: github.ref == 'refs/heads/master'
env:
SSH_HOST: ${{ secrets.SSH_HOST }}
SSH_USER: ${{ secrets.SSH_USER }}
PRODUCTION_PATH: ${{ secrets.PRODUCTION_PATH }}
run: |
echo "Deploying to PRODUCTION using Git Pull..."

# Deploy using git pull on server
ssh -i ~/.ssh/deploy_key -o StrictHostKeyChecking=no $SSH_USER@$SSH_HOST << 'ENDSSH'
set -e # Exit on error

echo "Changing to deployment directory..."
cd $PRODUCTION_PATH

echo "Fetching latest changes..."
git fetch origin master

echo "Creating backup tag..."
BACKUP_TAG="backup-production-$(date +%Y%m%d_%H%M%S)"
git tag -f $BACKUP_TAG HEAD
echo "Backup tag created: $BACKUP_TAG"

echo "Pulling latest code from master branch..."
git pull origin master

echo "Installing Composer dependencies..."
composer install --no-dev --optimize-autoloader --no-interaction

echo "Installing NPM dependencies..."
npm ci --production

echo "Building frontend assets..."
npx mix --production

echo "Generating blocklist..."
node generateBlocklist.mjs

echo "Clearing cache..."
# Clear cache files
sudo find bootstrap/cache -type f ! -name '.gitignore' -delete 2>/dev/null || true
sudo find storage/framework/cache -type f ! -name '.gitignore' -delete 2>/dev/null || true
sudo find storage/framework/sessions -type f ! -name '.gitignore' -delete 2>/dev/null || true
sudo find storage/framework/views -type f ! -name '.gitignore' -delete 2>/dev/null || true

echo "Setting proper file permissions..."
# Set ownership for application files
sudo chown -R www-data:www-data $PRODUCTION_PATH

# Secure .env file permissions
sudo chmod 600 config/.env 2>/dev/null || true

# Make writable directories
sudo chmod -R 775 storage bootstrap/cache userfiles public/userfiles 2>/dev/null || true

echo "Reloading services..."
# Reload PHP-FPM to clear opcache
sudo systemctl reload php8.2-fpm

# Reload nginx
sudo systemctl reload nginx

echo "Production deployment completed successfully!"
echo "Commit: $(git rev-parse --short HEAD)"
echo "Rollback available: git reset --hard $BACKUP_TAG"
ENDSSH

- name: Health Check Production
if: github.ref == 'refs/heads/master'
env:
PRODUCTION_URL: ${{ secrets.PRODUCTION_URL }}
run: |
echo " Running production health check..."
sleep 5

response=$(curl -s -o /dev/null -w "%{http_code}" $PRODUCTION_URL/healthCheck.php 2>/dev/null || echo "000")

if [ "$response" = "200" ]; then
echo " Production health check passed! (HTTP $response)"
else
echo " ERROR: Production health check failed! (HTTP $response)"
echo " Please verify the deployment manually at $PRODUCTION_URL"
exit 1
fi

- name: Deployment Summary
if: always()
run: |
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
if [ "${{ github.ref }}" = "refs/heads/develop" ]; then
echo " STAGING Deployment Summary"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Branch: develop"
echo "Environment: Staging"
echo "Server: ${{ secrets.SSH_HOST }}"
echo "Path: ${{ secrets.STAGING_PATH }}"
echo "URL: ${{ secrets.STAGING_URL }}"
else
echo " PRODUCTION Deployment Summary"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Branch: master"
echo "Environment: Production"
echo "Server: ${{ secrets.SSH_HOST }}"
echo "Path: ${{ secrets.PRODUCTION_PATH }}"
echo "URL: ${{ secrets.PRODUCTION_URL }}"
fi
echo "Commit: ${{ github.sha }}"
echo "Actor: ${{ github.actor }}"
echo "Status: ${{ job.status }}"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"

3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,6 @@ config/.env
/.serena
/.playwright-mcp
/.idea

.env
config/.env
Loading
Loading