Skip to content

Commit ab10c09

Browse files
committed
docs: Revise copilot instructions for clarity and structure, enhance developer workflows and error handling guidelines
1 parent 593c51d commit ab10c09

File tree

1 file changed

+145
-73
lines changed

1 file changed

+145
-73
lines changed

.github/copilot-instructions.md

Lines changed: 145 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -6,85 +6,157 @@ This document provides comprehensive guidance for AI coding agents and contribut
66

77
`ssh-key-sync` is a Bash script-based utility for synchronizing SSH `authorized_keys` files for multiple users. It supports fetching keys from various sources, including public URLs, private GitHub repositories, and GitHub user profiles. The configuration is externalized in a `users.conf` file.
88

9-
## Key Components
10-
11-
### Scripts
12-
- **`sync-ssh-keys.sh`**: The main script that performs the synchronization. It includes:
13-
- Support for multiple fetch methods (`raw`, `api`, `ghuser`).
14-
- Logging and error handling.
15-
- Configuration loading from `users.conf`.
16-
- A helper function `fetch_key_file` to handle key retrieval logic with retries for failed operations.
17-
- A `--self-update` option to fetch and replace the script with the latest version from the GitHub repository.
18-
19-
### Configuration
20-
- **`users.conf`**: Defines users and their key sources. Example structure:
21-
```bash
22-
CONF_GITHUB_TOKEN="your_github_token_here"
23-
24-
declare -A USER_KEYS=(
25-
["ubuntu"]="raw:https://example.com/ssh-keys/ubuntu.authorized_keys"
26-
["devuser"]="api:https://api.github.com/repos/yourorg/ssh-keys/contents/keys/devuser.authorized_keys?ref=main"
27-
["alice"]="ghuser:alice-github-username"
28-
)
29-
```
30-
31-
## Developer Workflows
32-
33-
### Running the Script
34-
1. Ensure `sync-ssh-keys.sh` is executable:
35-
```bash
36-
chmod +x sync-ssh-keys.sh
37-
```
38-
2. Run the script manually:
39-
```bash
40-
./sync-ssh-keys.sh
41-
```
42-
3. To update the script to the latest version, run:
43-
```bash
44-
./sync-ssh-keys.sh --self-update
45-
```
46-
47-
### Configuration
48-
- Edit `users.conf` to define users and their key sources.
49-
- If using the `api` method, ensure `CONF_GITHUB_TOKEN` is set in `users.conf` or export `GITHUB_TOKEN` in the environment.
50-
51-
### Automating with Cron
52-
- Add the script to root's crontab:
53-
```cron
54-
*/15 * * * * /path/to/sync-ssh-keys.sh >> /var/log/ssh-key-sync.log 2>&1
55-
```
56-
57-
### Logging
58-
- Logs are printed to the console with timestamps.
59-
- Example log message:
60-
```
61-
2025-07-20 12:00:00: Fetching key file for user 'ubuntu' from https://example.com/ssh-keys/ubuntu.authorized_keys (method: raw)
62-
```
63-
64-
## Coding Conventions
65-
66-
- Use meaningful variable and function names.
67-
- Follow the existing code style in `sync-ssh-keys.sh`.
68-
- Add comments for complex logic.
69-
- Use environment variables for sensitive data (e.g., `GITHUB_TOKEN`).
70-
- Ensure temporary files are cleaned up using `trap`.
9+
## Key Architecture Components
10+
11+
### Core Script Structure (`sync-ssh-keys.sh`)
12+
The main script follows a modular architecture with distinct functional layers:
13+
14+
- **Utility Functions** (lines 24-41): Timestamped logging functions (`log_message`, `log_error`, `log_warning`, `log_info`)
15+
- **Configuration Management** (lines 43-74): Configuration loading and validation with error handling
16+
- **Fetch Methods** (lines 76-174): Three distinct key fetching strategies with unified retry logic
17+
- **Self-Update System** (lines 176-272): Download, validate, and replace script functionality
18+
- **User Management** (lines 274-443): User validation, SSH directory creation, file permission management
19+
- **Main Execution** (lines 445-614): Command-line parsing, configuration sourcing, and orchestration
20+
21+
### Configuration Architecture (`users.conf`)
22+
Configuration uses Bash associative arrays for user-to-source mapping:
23+
```bash
24+
CONF_GITHUB_TOKEN="token_here" # Optional GitHub token
25+
declare -A USER_KEYS=(
26+
["username"]="method:target" # method:target pattern
27+
)
28+
```
29+
30+
### Three Key Fetch Methods
31+
1. **`raw`**: Direct HTTP(S) URL fetching (public endpoints)
32+
2. **`api`**: GitHub API with authentication (private repositories)
33+
3. **`ghuser`**: GitHub user public keys endpoint (`github.com/username.keys`)
34+
35+
## Critical Developer Workflows
36+
37+
### Testing Commands (Essential for Changes)
38+
```bash
39+
# Quick validation - Run before commits
40+
./test.sh
41+
42+
# Manual syntax check
43+
bash -n sync-ssh-keys.sh
44+
45+
# ShellCheck validation (if available)
46+
shellcheck sync-ssh-keys.sh
47+
48+
# Test with actual users (requires root)
49+
sudo ./sync-ssh-keys.sh
50+
```
51+
52+
### CI/CD Pipeline Structure
53+
The project uses a sophisticated multi-workflow CI system:
54+
- **`ci.yml`**: Orchestrates all checks (lint, test, version validation)
55+
- **`test.yml`**: Creates real users, tests all fetch methods, validates error handling
56+
- **`lint.yml`**: ShellCheck static analysis
57+
- **`check-version.yml`**: Ensures version bumps in PRs
58+
59+
### Configuration Testing Pattern
60+
Always test configuration changes with temporary configs:
61+
```bash
62+
cp users.conf users.conf.backup
63+
# Edit users.conf with test values
64+
sudo ./sync-ssh-keys.sh
65+
mv users.conf.backup users.conf
66+
```
67+
68+
### Error Handling Architecture
69+
The script uses a **defensive programming** approach:
70+
- Every function validates parameters and returns meaningful exit codes
71+
- Network operations include retry logic (3 attempts, 2-second delays)
72+
- Temporary file cleanup using `trap` statements
73+
- File comparison before updates to avoid unnecessary writes
74+
75+
### Self-Update Mechanism
76+
The `--self-update` feature demonstrates key patterns:
77+
- GitHub API integration for release information
78+
- Temporary file management with cleanup
79+
- Script validation before replacement
80+
- Atomic replacement to prevent corruption
81+
82+
## Project-Specific Conventions
83+
84+
### Function Organization Pattern
85+
Functions are grouped by responsibility with clear boundaries:
86+
- **Utilities**: Pure functions for logging (prefix: `log_`)
87+
- **Configuration**: Loading and validation (prefix: `load_`, `validate_`)
88+
- **Fetching**: Key retrieval methods (prefix: `fetch_`)
89+
- **User Management**: System operations (prefix: `create_`, `update_`, `process_`)
90+
91+
### Error Handling Style
92+
- Use meaningful exit codes: `return 1` for failures, `return 0` for success
93+
- Log errors before returning: `log_error "message"; return 1`
94+
- Validate parameters at function start: `[[ -z "$param" ]] && { log_error "message"; return 1; }`
95+
96+
### Bash Patterns Used
97+
- `set -euo pipefail` for strict error handling
98+
- Associative arrays for configuration: `declare -A USER_KEYS`
99+
- Here documents for multi-line content in tests
100+
- Parameter expansion for parsing: `${entry%%:*}` and `${entry#*:}`
101+
102+
### File Permission Management
103+
Critical pattern - always set correct permissions:
104+
```bash
105+
chown "$username:$username" "$file" # User ownership
106+
chmod 700 "$ssh_dir" # SSH directory
107+
chmod 600 "$auth_keys_file" # authorized_keys file
108+
```
71109

72110
## Integration Points
73111

74-
### GitHub API
75-
- Used for fetching keys from private repositories (`api` method).
76-
- Requires a GitHub token (`GITHUB_TOKEN` or `CONF_GITHUB_TOKEN`).
77-
78-
### System Integration
79-
- The script ensures the `.ssh` directory and `authorized_keys` file exist for each user.
80-
- Updates file permissions and ownership as needed.
112+
### GitHub API Integration
113+
- **Authentication**: Uses `GITHUB_TOKEN` or `CONF_GITHUB_TOKEN`
114+
- **Headers**: `Authorization: token $GITHUB_TOKEN` and `Accept: application/vnd.github.v3.raw`
115+
- **Rate Limiting**: Automatic retry logic helps with transient failures
116+
- **Private Repos**: Full API endpoint format required: `https://api.github.com/repos/org/repo/contents/path?ref=branch`
117+
118+
### System Dependencies
119+
- **`curl`**: All HTTP operations with `-fsSL` flags (fail silently, show errors, follow redirects, location headers)
120+
- **`getent`**: User information retrieval - more reliable than parsing `/etc/passwd`
121+
- **`mktemp`**: Secure temporary file creation with automatic cleanup
122+
- **File comparison tools**: `cmp` > `diff` > checksum fallback hierarchy
123+
124+
### File System Integration
125+
The script manages SSH infrastructure with specific patterns:
126+
- Creates `.ssh` directories with `700` permissions if missing
127+
- Compares files before updating to avoid unnecessary writes
128+
- Uses atomic operations (temp file → move) for updates
129+
- Maintains proper ownership chain: directory → file → permissions
81130

82131
## Contribution Guidelines
83132

84-
- Include a clear description of changes in pull requests.
85-
- Reference related issues.
86-
- Ensure the script passes linting (e.g., using `shellcheck`).
87-
- Test changes locally before submission.
133+
### Pre-Commit Validation
134+
```bash
135+
# Required: Syntax check
136+
bash -n sync-ssh-keys.sh
137+
138+
# Required: Run test suite
139+
./test.sh
140+
141+
# Recommended: Static analysis (if available)
142+
shellcheck sync-ssh-keys.sh
143+
```
144+
145+
### Version Management
146+
- Bump `SCRIPT_VERSION` in PRs (enforced by CI)
147+
- Follow semantic versioning (major.minor.patch)
148+
- Version check workflow prevents duplicate releases
149+
150+
### Code Quality Standards
151+
- All functions must validate input parameters
152+
- Use `log_error` before `return 1` in error conditions
153+
- Maintain consistent indentation (2 spaces)
154+
- Group related functions with clear section comments
155+
156+
### Testing Requirements
157+
- New fetch methods need integration tests in `test.yml`
158+
- Configuration changes require validation tests
159+
- Error conditions must be tested with invalid inputs
88160

89161
## Examples
90162

0 commit comments

Comments
 (0)