1- # LaunchDarkly Flag Expiry Setter Action
1+ # LaunchDarkly Flag Expiry Setter
22
3- A GitHub Action that automatically sets expiry date custom properties on LaunchDarkly feature flags based on their creation dates. This action helps teams proactively manage feature flag lifecycle at enterprise scale by automatically calculating and setting expiration dates.
3+ [ ![ License: MIT ] ( https://img.shields.io/badge/License-MIT-yellow.svg )] ( https://opensource.org/licenses/MIT )
44
5- ## Features
5+ A GitHub Action that manages LaunchDarkly feature flag custom properties by setting an expiry date based on flag creation timestamps.
66
7- - 🚀 ** Fully Automated** : Processes all flags in a project automatically - no manual flag selection needed
8- - 📅 ** Creation Date Based** : Calculates expiry dates from actual flag creation timestamps
9- - 🔄 ** Enterprise Scale** : Handles thousands of flags with proper pagination and rate limiting
10- - 📊 ** Smart Filtering** : Skips flags that already have expiry dates (configurable)
11- - 🎯 ** Flexible Date Formats** : Supports MM/DD/YYYY, YYYY-MM-DD, MM-DD-YYYY, YYYY/MM/DD
12- - 🛡️ ** Rate Limit Handling** : Built-in 429 retry logic with exponential backoff
13- - ⚡ ** Batch Processing** : Processes flags in batches to avoid API overwhelm
14- - 📋 ** Comprehensive Reporting** : Detailed summaries of processed, skipped, and failed flags
15- - 🔧 ** Configurable** : Customizable expiry periods, property names, and date formats
7+ > ** ⚠️ Disclaimer** : This is not an officially supported LaunchDarkly solution. Use at your own discretion.
168
17- ## How It Works
9+ ## Configuration
1810
19- 1 . ** Fetches all flags** in the specified LaunchDarkly project (with pagination)
20- 2 . ** Filters flags** that need expiry dates (skips existing if configured)
21- 3 . ** Calculates expiry dates** by adding specified days to each flag's creation date
22- 4 . ** Sets custom properties** in batches with rate limiting
23- 5 . ** Reports results** with comprehensive success/failure breakdown
11+ ### Input Parameters
2412
25- ## Usage
13+ | Parameter | Description | Required | Default | Example |
14+ | -----------| -------------| ----------| ---------| ---------|
15+ | ` launchdarkly_api_key ` | LaunchDarkly API access token (requires WRITE permission) | ✅ | - | ` ${{ secrets.LAUNCHDARKLY_API_KEY }} ` |
16+ | ` project_key ` | LaunchDarkly project key | ✅ | - | ` my-project ` |
17+ | ` days_from_creation ` | Number of days from flag creation date to set expiry | ❌ | ` 30 ` | ` 90 ` |
18+ | ` custom_property_name ` | Name of the custom property to set | ❌ | ` flag.expiry.date ` | ` lifecycle.expiry.date ` |
19+ | ` date_format ` | Date format for the expiry date | ❌ | ` MM/DD/YYYY ` | ` YYYY-MM-DD ` |
20+ | ` skip_existing ` | Skip flags that already have the expiry property set | ❌ | ` true ` | ` false ` |
2621
27- This is not an officially supported solution. Use at your own risk.
22+ ### Supported Date Formats
2823
29- ### Basic Example - Set 30-day Expiry on All Flags
24+ | Format | Example | Description |
25+ | --------| ---------| -------------|
26+ | ` MM/DD/YYYY ` | ` 03/15/2024 ` | US format (default) |
27+ | ` MM-DD-YYYY ` | ` 03-15-2024 ` | US format with dashes |
28+ | ` YYYY-MM-DD ` | ` 2024-03-15 ` | ISO 8601 format |
29+ | ` YYYY/MM/DD ` | ` 2024/03/15 ` | International format |
30+
31+ ### Output Parameters
32+
33+ | Output | Type | Description |
34+ | --------| ------| -------------|
35+ | ` updated_flags ` | JSON Array | Flags that were successfully updated with expiry dates |
36+ | ` failed_flags ` | JSON Array | Flags that failed to update with error details |
37+ | ` skipped_flags ` | JSON Array | Flags that were skipped with reasons |
38+ | ` total_processed ` | Number | Total number of flags that were processed |
39+ | ` total_found ` | Number | Total number of flags found in the project |
40+ | ` total_skipped ` | Number | Total number of flags that were skipped |
41+
42+ ## Quick Start
43+
44+ ### Basic Usage
3045
3146``` yaml
3247name : Set Flag Expiry Dates
4964 days_from_creation : ' 30'
5065` ` `
5166
52- ### Advanced Example - Custom Configuration
67+ ### Advanced Configuration
5368
5469` ` ` yaml
5570name : Flag Lifecycle Management
@@ -117,40 +132,12 @@ jobs:
117132 project_key : ' your-project'
118133 days_ahead : ' 7'
119134 create_issues : ' true'
120- ` ` `
121-
122- ## Inputs
123-
124- | Input | Description | Required | Default |
125- |-------|-------------|----------|---------|
126- | ` launchdarkly_api_key` | LaunchDarkly API access token (requires WRITE permission) | Yes | |
127- | `project_key` | LaunchDarkly project key | Yes | |
128- | `days_from_creation` | Number of days from flag creation date to set expiry | No | `30` |
129- | `custom_property_name` | Name of the custom property to set | No | `flag.expiry.date` |
130- | `date_format` | Date format for the expiry date | No | `MM/DD/YYYY` |
131- | `skip_existing` | Skip flags that already have the expiry property set | No | `true` |
132-
133- # ## Date Format Options
134-
135- - ` MM/DD/YYYY` (e.g., `03/15/2024`) - **Default**
136- - ` MM-DD-YYYY` (e.g., `03-15-2024`)
137- - ` YYYY-MM-DD` (e.g., `2024-03-15`)
138- - ` YYYY/MM/DD` (e.g., `2024/03/15`)
139-
140- # # Outputs
141135
142- | Output | Description |
143- |--------|-------------|
144- | `updated_flags` | JSON array of flags that were successfully updated |
145- | `failed_flags` | JSON array of flags that failed to update |
146- | `skipped_flags` | JSON array of flags that were skipped |
147- | `total_processed` | Total number of flags processed |
148- | `total_found` | Total number of flags found in the project |
149- | `total_skipped` | Total number of flags skipped |
136+ # # Output Examples
150137
151- # ## Output Format Examples
138+ <details>
139+ <summary><strong>Successfully Updated Flags</strong></summary>
152140
153- # ### Successfully Updated Flags
154141` ` ` json
155142[
156143 {
@@ -163,8 +150,11 @@ jobs:
163150 }
164151]
165152` ` `
153+ </details>
154+
155+ <details>
156+ <summary><strong>Skipped Flags</strong></summary>
166157
167- # ### Skipped Flags
168158` ` ` json
169159[
170160 {
@@ -175,49 +165,28 @@ jobs:
175165 }
176166]
177167` ` `
168+ </details>
178169
179- # # API Requirements
180-
181- # ## LaunchDarkly API Token
182-
183- This action requires a LaunchDarkly API access token with **WRITE permissions** for feature flags.
184-
185- To create an API token :
186-
187- 1. Go to **Account settings** > **Authorization** in LaunchDarkly
188- 2. Click **Create token**
189- 3. Provide a name for your token
190- 4. Select a role with write permissions (Writer or Admin)
191- 5. Choose the projects you want to modify
192- 6. Save the token as a GitHub secret (e.g., `LAUNCHDARKLY_API_KEY`)
170+ # # Prerequisites
193171
194- # ## Required Permissions
172+ # ## LaunchDarkly API Token Setup
195173
196- The API token needs :
197- - **Write access** to feature flags in the specified project
198- - Permission to modify custom properties
174+ > **🔐 Security Note**: This action requires write access to your LaunchDarkly feature flags.
199175
200- # # Enterprise Features
176+ **Required Permissions:**
177+ - ✅ Write access to feature flags in the target project
178+ - ✅ Permission to modify custom properties
201179
202- # ## Automatic Pagination
203- - Handles projects with thousands of flags
204- - Processes all flags automatically with proper API pagination
205- - Progress tracking for large datasets
180+ **Setup Instructions:**
181+ 1. Navigate to **Account Settings** → **Authorization** in LaunchDarkly
182+ 2. Click **Create Token**
183+ 3. Configure the token :
184+ - **Name**: `GitHub Actions Flag Expiry Setter`
185+ - **Role**: Writer or Admin
186+ - **Projects**: Select target projects
187+ 4. Copy the token and add it to GitHub Secrets as `LAUNCHDARKLY_API_KEY`
206188
207- # ## Rate Limiting & Retry Logic
208- - Built-in 429 (rate limit) handling with exponential backoff
209- - Configurable delays between API requests
210- - Automatic retry on transient failures
211-
212- # ## Batch Processing
213- - Processes flags in configurable batches (default : 10 flags per batch)
214- - Parallel processing within batches, sequential between batches
215- - Prevents API overwhelm while maintaining efficiency
216-
217- # ## Intelligent Filtering
218- - Automatically skips flags with invalid/missing creation dates
219- - Configurable skip logic for flags with existing expiry properties
220- - Detailed reporting of why flags were skipped
189+ > **⚠️ Important**: Store the API token securely in GitHub Secrets. Never commit it to your repository.
221190
222191# # Common Use Cases
223192
@@ -276,95 +245,32 @@ Ensure all flags have expiry dates for audit purposes:
276245 days_from_creation: '180'
277246` ` `
278247
279- # # Error Handling
280-
281- The action includes comprehensive error handling for :
282-
283- - **Invalid API credentials** - Clear guidance on token requirements
284- - **Missing flags** - Graceful handling of flags without creation dates
285- - **Permission errors** - Specific messaging about write permissions
286- - **Network connectivity issues** - Automatic retry with exponential backoff
287- - **Rate limiting** - Built-in 429 handling per LaunchDarkly's guidelines
288- - **API failures** - Detailed error reporting with context
289-
290- # # Performance & Scale
291-
292- # ## Tested At Scale
293- - ✅ **1000+ flags** - Handles large enterprise projects
294- - ✅ **Rate limiting** - Respects LaunchDarkly API limits
295- - ✅ **Memory efficient** - Processes flags in batches
296- - ✅ **Progress tracking** - Real-time updates for long-running operations
297-
298- # ## Typical Performance
299- - **Small projects** (< 50 flags): ~30 seconds
300- - **Medium projects** (50-500 flags): 2-5 minutes
301- - **Large projects** (500+ flags): 5-15 minutes
302-
303- Performance depends on :
304- - Number of flags in project
305- - API response times
306- - Rate limiting encounters
307- - Batch size configuration
308-
309248# # Troubleshooting
310249
311- # ## Common Issues
312-
313- 1. **"Please check your API key has WRITE permissions"**
314- - Ensure your API token has write access to feature flags
315- - Verify the token hasn't expired
316-
317- 2. **"Invalid creation date for flag"**
318- - Some flags may have missing or invalid creation dates
319- - These flags are automatically skipped with detailed reporting
320-
321- 3. **Rate limiting errors**
322- - The action handles rate limiting automatically
323- - For very large projects, the action may take longer but will complete
324-
325- 4. **"No flags to process"**
326- - All flags already have expiry dates (when `skip_existing : true`)
327- - Check the skipped flags output for details
328-
329- # ## Debug Mode
330-
331- Enable debug logging by setting the `ACTIONS_STEP_DEBUG` secret to `true` in your repository.
250+ # ## Common Issues & Solutions
332251
333- # # Integration with Other Tools
252+ | Issue | Cause | Solution |
253+ |-------|-------|----------|
254+ | **"API key has no WRITE permissions"** | Insufficient token permissions | Ensure API
255+ | **Rate limiting errors** | Too many API requests | Built-in handling with exponential backoff |
334256
335- # ## LaunchDarkly Flag Expiry Audit Action
336- Perfect companion for complete flag lifecycle management :
337- ` ` ` yaml
338- # Set expiry dates
339- - uses: your-org/launchdarkly-flag-expiry-setter@v1
340- # ... configuration ...
257+ # # Contributing
341258
342- # Audit expiring flags
343- - uses: devopsdina/ld-cp-exp-date-gh-actions-audit@v1
344- # ... configuration ...
345- ` ` `
259+ We welcome contributions! Please see our [contribution guidelines](CONTRIBUTING.md) for details.
346260
347- # ## Slack Notifications
348- Combine with Slack actions for team notifications :
349- ` ` ` yaml
350- - name: Notify team of flag updates
351- uses: 8398a7/action-slack@v3
352- with:
353- status: custom
354- custom_payload: |
355- {
356- text: "Updated expiry dates on ${{ steps.set-expiry.outputs.total_processed }} flags"
357- }
358- ` ` `
261+ # ## Development Setup
262+ 1. Fork the repository
263+ 2. Create a feature branch
264+ 3. Make your changes
265+ 4. Run tests : ` npm test`
266+ 5. Submit a pull request
359267
360- # # Contributing
268+ # # Related Projects
361269
362- Contributions are welcome! Please feel free to submit a Pull Request.
270+ | Project | Description | Link |
271+ |---------|-------------|------|
272+ | **Flag Expiry Audit** | Audit flags for expiring dates | [GitHub](https://github.com/devopsdina/ld-cp-exp-date-gh-actions-audit) |
363273
364274# # License
365275
366- This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
367-
368- # # Related Actions
369-
370- - [LaunchDarkly Flag Expiry Audit](https://github.com/devopsdina/ld-cp-exp-date-gh-actions-audit) - Audit flags for expiring dates
276+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
0 commit comments