Skip to content

Commit da95b7e

Browse files
authored
Architectural Refactoring Completion (#7)
* feat(service): add GitHubService to modularize octokit operations - creates src/services/github.service.ts with an isolated class responsible for the renameBranch call. - implements an open parameter pattern, without ActionInputs dependencies. - encapsulates typed calls using octokit.rest.repos.renameBranch. * refactor(core): rename index.ts to main.ts and make it a pure orchestrator - completely remove index.ts from the main flow. - create main.ts containing only the action execution/orchestration function. - move all business logic to specialized services according to srp standards. * chore(build): adjust package.json for new entrypoint and build command - updates internal references to point to main.ts as the entry point. - adjusts the typescript compiler (tsc) configuration according to the new structure. - ensures that the build correctly generates the dist/index.js artifact with the new modular flow. * build: update dist/index.js artifact after structural refactoring - regenerates dist/index.js reflecting the changes in main.ts and the new githubservice. - removes legacy code that was previously present in index.ts. - updated artifact generated by typescript without manual changes. * documenting...
1 parent 1f8a7ad commit da95b7e

5 files changed

Lines changed: 100 additions & 32033 deletions

File tree

README.md

Lines changed: 62 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ This is useful for teams who want to **automate branch maintenance or enforce na
2424
### 2. **Example Workflow Integration**
2525

2626
```yaml
27-
name: Rename Branch
27+
name: Test Rename Branch
2828

2929
on:
3030
workflow_dispatch:
@@ -52,7 +52,7 @@ jobs:
5252
runs-on: ubuntu-latest
5353
steps:
5454
- name: Exec Branch Shift
55-
uses: ws2git/branch-shift@v1.5
55+
uses: ws2git/branch-shift@v2
5656

5757
with:
5858
github-token: ${{ secrets.YOUR_PAT }}
@@ -76,44 +76,78 @@ jobs:
7676

7777
## ⚙️ How It Works
7878

79-
This action executes a **Node.js script** (`dist/index.js`) that uses the GitHub API to perform two main steps to effectively "rename" a branch:
79+
This action executes a **Node.js script** (`dist/index.js`) that uses the GitHub API to rename a branch through a single, atomic operation. The action follows a clean, modular architecture with clear separation of concerns.
8080

81-
1. **Create a New Branch:** It creates a new branch using the `new_name` that points to the same commit as the `branch` (the old name).
82-
2. **Delete the Old Branch:** It deletes the original `branch` (the old name).
81+
**Execution Flow:**
8382

84-
The use of a Node.js script allows for precise control over the API calls.
83+
1. **Input Validation & Configuration**
84+
- The `ConfigManager` validates all required inputs (`github-token`, `owner`, `repo`, `branch`, `new_name`)
85+
- Ensures proper formatting and non-empty values
86+
- Converts input names from `snake_case` to `camelCase` for internal use
8587

86-
**Script logic (Conceptual):**
88+
2. **GitHub API Operation**
89+
- The `GitHubService` uses the official GitHub Octokit SDK with full TypeScript typing
90+
- Makes a single API call to `repos.renameBranch` endpoint
91+
- Uses GitHub API version `2022-11-28` for compatibility
8792

88-
```javascript
89-
// Step 1: Create a new branch pointing to the old branch's commit SHA
90-
const create_ref_url = `/repos/${owner}/${repo}/git/refs`;
91-
// API Call: POST /repos/{owner}/{repo}/git/refs
92-
// Body: { "ref": "refs/heads/new_name", "sha": <SHA_of_old_branch> }
93-
94-
// Step 2: Delete the old branch
95-
const delete_ref_url = `/repos/${owner}/${repo}/git/refs/heads/${branch}`;
96-
// API Call: DELETE /repos/{owner}/{repo}/git/refs/heads/branch
93+
**Core Implementation:**
9794

95+
```typescript
96+
// Single API call handling both creation and deletion internally
97+
await this.octokit.rest.repos.renameBranch({
98+
owner,
99+
repo,
100+
branch, // Current branch name
101+
new_name: newName // Target branch name
102+
});
98103
```
99104

100-
If **any required parameter is missing** or the **token lacks the necessary permissions**, the script will exit with an error.
105+
**Key Advantages:**
106+
107+
- **Atomic Operation**: GitHub's native `renameBranch` handles both creation and deletion in one API call
108+
- **Type Safety**: Uses typed Octokit SDK methods instead of generic REST calls
109+
- **Fail Fast**: Comprehensive input validation before any API calls
110+
- **Clean Architecture**: Separated concerns between configuration, orchestration, and service layers
111+
112+
If **any required parameter is missing**, **input validation fails**, or the **token lacks necessary permissions**, the action will exit immediately with a descriptive error message.
101113

102114

103115
## 🛡️ Security and Authentication
104116

105-
This Action requires a GitHub Token with **write permissions** on the repository to perform branch operations. The token is passed via the **`github_token` input**.
117+
This Action requires a GitHub Token with **write permissions** to perform branch operations. The token is passed via the **`github-token` input** (note the exact parameter name).
118+
119+
**Token Requirements:**
120+
121+
The provided token must have sufficient permissions to call the GitHub API's `repos.renameBranch` endpoint. This typically requires:
122+
- **`repo` scope** for personal access tokens
123+
- **Write access** to the repository contents
124+
125+
**Recommended Setup:**
106126

107-
**Recommended**: Since renaming a branch is a highly privileged operation, it's highly recommended to use a **Personal Access Token (PAT)** stored as a **Secret** that explicitly has the `repo` scope, as the default **`${{ github.token }}`** might not have sufficient permissions, especially in organizational setups.
127+
For most scenarios, especially in organizational contexts, we recommend using a **Personal Access Token (PAT)** stored as a repository secret:
108128

109129
```yaml
110-
env:
111-
# Using an explicitly created Secret PAT (e.g., REPO_RENAME_TOKEN)
112-
# stored in your repository secrets.
113-
GH_TOKEN: ${{ secrets.REPO_RENAME_TOKEN }}
130+
- name: Branch Rename
131+
uses: ws2git/branch-shift@v2
132+
with:
133+
github-token: ${{ secrets.REPO_RENAME_TOKEN }}
134+
owner: ${{ github.repository_owner }}
135+
repo: ${{ github.event.repository.name }}
136+
branch: 'old-branch-name'
137+
new_name: 'new-branch-name'
138+
```
139+
140+
**Alternative Options:**
141+
142+
```yaml
143+
# Using GitHub's automatically provided token (may have limited permissions)
144+
github-token: ${{ github.token }}
145+
146+
# Using a custom PAT with explicit repo scope
147+
github-token: ${{ secrets.REPO_RENAME_TOKEN }}
114148
```
115149

116-
**Never expose the PAT in plain text.**
150+
For production use, create a dedicated PAT with minimal required scopes and store it securely in your repository secrets.
117151

118152

119153
## 📌 Notes
@@ -126,6 +160,10 @@ These are the important points to consider regarding the branch renaming operati
126160

127161
* **Default Token Limitation**: The default token (`${{ github.token }}`) might be read-only or lack the necessary permissions to delete or create branches via the API, especially in certain contexts (like PRs from forks) or with stricter organization security settings.
128162
* **PAT is Safer**: For Actions that modify the repository structure (like renaming/deleting branches), using a **dedicated PAT stored as a secret** is the most reliable approach.
163+
* The token is validated early in the execution flow via ConfigManager
164+
* Invalid or insufficient tokens will cause immediate action failure
165+
* Token values are never logged or exposed in output
166+
* Never hardcode tokens in workflow files - always use secrets
129167

130168

131169
## 🔗 Related Documentation

0 commit comments

Comments
 (0)