Planning around scheduled freezes just got a whole lot easier! We’re excited to announce that our Branch API endpoints now include next_freeze_at
and next_unfreeze_at
epoch timestamps, giving you precise visibility into upcoming freeze events.
What’s New
Every Branch API response now includes two powerful new fields:
{
"frozen": false,
"allow_deployments": true,
"branch": "main",
"repository": "my-app",
"organization": "my-org",
"next_freeze_at": 1666310400,
"next_unfreeze_at": 1666324800,
"last_updated": "2022-10-20T10:00:00Z"
}
Understanding the Timestamps
next_freeze_at
: Unix epoch timestamp of the next scheduled freezenext_unfreeze_at
: Unix epoch timestamp of the next scheduled unfreezenull
values: Returned when no freeze/unfreeze is scheduled
Building Proactive Automation
Predictable Automation
Build smarter CI/CD pipelines that know exactly when freezes will occur:
const response = await fetch('/api/branches/myorg/myrepo/main?access_token=TOKEN');
const branchData = await response.json();
if (branchData.next_freeze_at) {
const nextFreeze = new Date(branchData.next_freeze_at * 1000);
const timeUntilFreeze = nextFreeze - new Date();
if (timeUntilFreeze < 30 * 60 * 1000) { // 30 minutes
console.log('â ī¸ Freeze scheduled in less than 30 minutes - delaying deployment');
// Implement delay or alternative strategy
}
}
Better Team Communication
Automatically inform your team about upcoming freezes:
#!/bin/bash
# Daily freeze check script
RESPONSE=$(curl -s "https://www.mergefreeze.com/api/branches/myorg/myrepo/main?access_token=$TOKEN")
NEXT_FREEZE=$(echo $RESPONSE | jq -r '.next_freeze_at')
if [ "$NEXT_FREEZE" != "null" ]; then
FREEZE_TIME=$(date -d "@$NEXT_FREEZE" '+%Y-%m-%d %H:%M:%S')
echo "đ¨ Upcoming freeze: $FREEZE_TIME"
# Send to Slack, email, or other notification system
curl -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"Upcoming freeze for myrepo/main: $FREEZE_TIME\"}" \
$SLACK_WEBHOOK_URL
fi
Integration with Monitoring Tools
Connect freeze schedules with your monitoring and alerting systems:
import requests
from datetime import datetime, timedelta
def check_freeze_schedule(org, repo, branch, token):
"""Check if a freeze is scheduled soon and adjust monitoring accordingly"""
url = f"https://www.mergefreeze.com/api/branches/{org}/{repo}/{branch}"
params = {"access_token": token}
response = requests.get(url, params=params)
data = response.json()
if data.get('next_freeze_at'):
next_freeze = datetime.fromtimestamp(data['next_freeze_at'])
time_until_freeze = next_freeze - datetime.now()
if time_until_freeze < timedelta(hours=2):
# Adjust monitoring thresholds before freeze
print(f"Freeze in {time_until_freeze} - adjusting alert thresholds")
return {"action": "prepare_for_freeze", "freeze_time": next_freeze}
return {"action": "normal_operations"}
# Use in your monitoring pipeline
schedule_info = check_freeze_schedule("myorg", "myrepo", "main", "your-token")
Real-World Use Cases
Deployment Pipeline Intelligence
# GitHub Actions example
name: Smart Deployment
on:
push:
branches: [main]
jobs:
check-freeze-schedule:
runs-on: ubuntu-latest
outputs:
should-deploy: ${{ steps.freeze-check.outputs.should-deploy }}
freeze-time: ${{ steps.freeze-check.outputs.freeze-time }}
steps:
- name: Check freeze schedule
id: freeze-check
run: |
RESPONSE=$(curl -s "https://www.mergefreeze.com/api/branches/${{ github.repository_owner }}/${{ github.event.repository.name }}/main" \
-H "Authorization: Bearer ${{ secrets.MERGE_FREEZE_TOKEN }}")
NEXT_FREEZE=$(echo $RESPONSE | jq -r '.next_freeze_at')
if [ "$NEXT_FREEZE" != "null" ]; then
CURRENT_TIME=$(date +%s)
TIME_UNTIL_FREEZE=$((NEXT_FREEZE - CURRENT_TIME))
if [ $TIME_UNTIL_FREEZE -lt 1800 ]; then # 30 minutes
echo "should-deploy=false" >> $GITHUB_OUTPUT
echo "freeze-time=$(date -d @$NEXT_FREEZE)" >> $GITHUB_OUTPUT
else
echo "should-deploy=true" >> $GITHUB_OUTPUT
fi
else
echo "should-deploy=true" >> $GITHUB_OUTPUT
fi
deploy:
needs: check-freeze-schedule
runs-on: ubuntu-latest
if: needs.check-freeze-schedule.outputs.should-deploy == 'true'
steps:
- name: Deploy to production
run: |
echo "Deploying - no freeze scheduled soon"
# Your deployment steps here
Weekend Freeze Awareness
// Check for weekend freezes in your deployment dashboard
async function getWeekendFreezeStatus() {
const repos = ['frontend', 'api', 'database', 'auth-service'];
const freezeSchedule = [];
for (const repo of repos) {
const response = await fetch(`/api/branches/myorg/${repo}/main?access_token=TOKEN`);
const data = await response.json();
if (data.next_freeze_at) {
const freezeDate = new Date(data.next_freeze_at * 1000);
const isWeekend = freezeDate.getDay() === 0 || freezeDate.getDay() === 6;
if (isWeekend) {
freezeSchedule.push({
repo: repo,
freeze_time: freezeDate,
day: freezeDate.toLocaleDateString('en-US', { weekday: 'long' })
});
}
}
}
return freezeSchedule;
}
// Display weekend freeze warnings
getWeekendFreezeStatus().then(schedule => {
if (schedule.length > 0) {
console.log('đī¸ Weekend freezes scheduled:');
schedule.forEach(item => {
console.log(` ${item.repo}: ${item.day} at ${item.freeze_time.toLocaleTimeString()}`);
});
}
});
Maintenance Window Coordination
# Coordinate maintenance windows across multiple services
#!/bin/bash
SERVICES=("web-app" "api-gateway" "user-service" "payment-processor")
MAINTENANCE_START=$(date -d "today 2 AM" +%s)
MAINTENANCE_END=$(date -d "today 6 AM" +%s)
echo "Checking freeze schedules for maintenance window..."
echo "Maintenance: $(date -d @$MAINTENANCE_START) to $(date -d @$MAINTENANCE_END)"
echo ""
for SERVICE in "${SERVICES[@]}"; do
RESPONSE=$(curl -s "https://www.mergefreeze.com/api/branches/myorg/$SERVICE/main?access_token=$TOKEN")
NEXT_FREEZE=$(echo $RESPONSE | jq -r '.next_freeze_at')
NEXT_UNFREEZE=$(echo $RESPONSE | jq -r '.next_unfreeze_at')
echo "đĻ $SERVICE:"
if [ "$NEXT_FREEZE" != "null" ]; then
if [ $NEXT_FREEZE -le $MAINTENANCE_END ] && [ $NEXT_FREEZE -ge $MAINTENANCE_START ]; then
echo " â
Freeze aligns with maintenance window"
else
echo " â ī¸ Freeze scheduled outside maintenance window: $(date -d @$NEXT_FREEZE)"
fi
else
echo " âšī¸ No freeze scheduled"
fi
done
Advanced Integration Patterns
Database-Driven Freeze Tracking
-- Store freeze schedules in your database for complex queries
CREATE TABLE freeze_schedules (
id SERIAL PRIMARY KEY,
organization VARCHAR(100) NOT NULL,
repository VARCHAR(100) NOT NULL,
branch VARCHAR(100) NOT NULL,
next_freeze_at TIMESTAMP,
next_unfreeze_at TIMESTAMP,
last_updated TIMESTAMP DEFAULT NOW()
);
-- Sample query to find all repos with freezes this weekend
SELECT organization, repository, branch, next_freeze_at
FROM freeze_schedules
WHERE EXTRACT(DOW FROM next_freeze_at) IN (0, 6) -- Sunday or Saturday
AND next_freeze_at > NOW()
AND next_freeze_at < NOW() + INTERVAL '7 days';
Slack Bot Integration
// Slack bot that reports upcoming freezes
app.command('/freeze-schedule', async ({ command, ack, respond }) => {
await ack();
const repos = command.text ? [command.text] : await getDefaultRepos();
const schedules = [];
for (const repo of repos) {
const response = await fetch(`https://www.mergefreeze.com/api/branches/myorg/${repo}/main?access_token=${process.env.MERGE_FREEZE_TOKEN}`);
const data = await response.json();
if (data.next_freeze_at) {
schedules.push({
repo: repo,
freeze_time: new Date(data.next_freeze_at * 1000),
unfreeze_time: data.next_unfreeze_at ? new Date(data.next_unfreeze_at * 1000) : null
});
}
}
if (schedules.length === 0) {
await respond('đ No freezes scheduled for the specified repositories!');
} else {
const message = schedules.map(s =>
`đ§ *${s.repo}*: Freeze at ${s.freeze_time.toLocaleString()}` +
(s.unfreeze_time ? ` â Unfreeze at ${s.unfreeze_time.toLocaleString()}` : '')
).join('\n');
await respond(`đ
*Upcoming Freeze Schedule:*\n${message}`);
}
});
Migration and Compatibility
Backward Compatibility
- Existing integrations continue to work - these are additional fields
- Null handling - fields return
null
when no freeze is scheduled - Epoch format - Standard Unix timestamps for easy conversion
Testing Your Integration
# Test with a repository that has scheduled freezes
curl "https://www.mergefreeze.com/api/branches/your-org/your-repo/main?access_token=YOUR_TOKEN" | jq '.'
# Expected output:
{
"frozen": false,
"next_freeze_at": 1666310400,
"next_unfreeze_at": 1666324800,
// ... other fields
}
Best Practices
1. Handle Null Values
Always check if timestamps exist before using them:
if (data.next_freeze_at !== null) {
const nextFreeze = new Date(data.next_freeze_at * 1000);
// Process freeze time
}
2. Cache Responsibly
Schedule data doesn’t change frequently, so caching is appropriate:
// Cache for 5 minutes
const CACHE_TTL = 5 * 60 * 1000;
3. Time Zone Awareness
Convert epoch timestamps to appropriate time zones:
const localTime = new Date(epochTimestamp * 1000).toLocaleString('en-US', {
timeZone: 'America/New_York',
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
hour: 'numeric',
minute: 'numeric'
});
Ready to build smarter automation around your freeze schedules?
These timestamp enhancements make it easier than ever to build intelligent deployment workflows that work seamlessly with your freeze schedules.
Your automation can now be truly proactive! đ