-
-
Notifications
You must be signed in to change notification settings - Fork 5
feat(gh-action): create workflow for automatize stable-main creation #69
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
29 commits
Select commit
Hold shift + click to select a range
d04e7cf
feat(gh-action): create workflow for automatize stable-main creation
alucardzom 70f94aa
chore: remove unused input
alucardzom 9dcf8bd
chore: update stable sync
alucardzom 6fea9a0
chore: added workflow call
alucardzom 887c99d
chore: pin pr action from v7 to v5
alucardzom e7c2d75
chore: comment the Create PR step, to test previous one before
alucardzom c9473ee
chore: set user and email
alucardzom 51937a5
chore: added global as well
alucardzom 373fb6d
chore: enable create PR on GH toolkit
alucardzom 9664956
chore: commented peter evans PR create step
alucardzom a769465
chore: added CREATE_BRANCH env for the sync step
alucardzom cafe053
chore: improve the template
alucardzom 23607c1
chore: update adding env var to create branch
alucardzom 3b26c04
chore: add gh command to push the branch
alucardzom fcfd2d3
chore: test create with gh command
alucardzom 3a67a8e
chore: gh auth login
alucardzom 0279f78
chore: test without using gh
alucardzom 93207bd
chore: improve body PR
alucardzom 34c5d2c
chore: update sync script
alucardzom 84d60c0
chore: execute chantes even if the PR exists
alucardzom 85aeea3
chore: check for push outside of the box
alucardzom fe969ac
chore: added pull before push
alucardzom 805133a
chore: tes new script changes
alucardzom 0795ec6
chore: push
alucardzom 7752444
chore: test
alucardzom 1cbd044
chore: improve script for mobile and extension
alucardzom d543dd0
chore: clean up body message
alucardzom 68cdc5f
chore: lint yaml
alucardzom 22dc82d
chore: linter passed
alucardzom File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,175 @@ | ||
| #!/usr/bin/env node | ||
|
|
||
| // USAGE: | ||
| // This will create/update a local stable-sync branch | ||
| // and get it in the state needed for a stable-sync PR | ||
| // Once the script successfully completes, you just | ||
| // need to push the branch to the remote repo. This will | ||
| // likely require a `git push --force` | ||
| // | ||
| // Usage: node stable-sync.js [branch-name] | ||
| // If no branch name is provided, defaults to 'stable-sync' | ||
| // | ||
| // Environment variables: | ||
| // CREATE_BRANCH - if set to 'true', will push the branch at the end | ||
|
|
||
| const { promisify } = require('util'); | ||
| const exec = promisify(require('child_process').exec); | ||
|
|
||
| async function runGitCommands() { | ||
| // Get branch name from command line arguments or use default | ||
| const branchName = process.argv[2] || 'stable-main'; | ||
|
|
||
| // Check if CREATE_BRANCH environment variable exists and is set to true | ||
| const shouldPushBranch = (process.env.CREATE_BRANCH || 'false').toLowerCase() === 'true'; | ||
|
|
||
| try { | ||
| try { | ||
| // Check if the branch already exists | ||
| const { stdout: branchExists } = await exec( | ||
| //`git rev-parse --quiet --verify ${branchName}`, | ||
| `git ls-remote origin ${branchName}`, | ||
| ); | ||
| if (branchExists.trim()) { | ||
| // Branch exists, so simply check it out | ||
| await exec(`git checkout ${branchName}`); | ||
| await exec(`git pull origin ${branchName}`); | ||
| console.log(`Checked out branch: ${branchName}`); | ||
| } else { | ||
| throw new Error( | ||
| 'git rev-parse --quiet --verify failed. Branch hash empty', | ||
| ); | ||
| } | ||
| } catch (error) { | ||
| if (error.stdout === '') { | ||
| console.warn( | ||
| `Branch does not exist, creating new ${branchName} branch.`, | ||
| ); | ||
|
|
||
| // Branch does not exist, create and check it out | ||
| await exec(`git checkout -b ${branchName}`); | ||
| console.log(`Created and checked out branch: ${branchName}`); | ||
| } else { | ||
| console.error(`Error: ${error.message}`); | ||
| process.exit(1); | ||
| } | ||
| } | ||
|
|
||
| await exec('git fetch'); | ||
| console.log('Executed: git fetch'); | ||
|
|
||
| await exec('git reset --hard origin/stable'); | ||
| console.log('Executed: git reset --hard origin/stable'); | ||
|
|
||
| try { | ||
| await exec('git merge origin/main'); | ||
| console.log('Executed: git merge origin/main'); | ||
| } catch (error) { | ||
| // Handle the error but continue script execution | ||
| if ( | ||
| error.stdout.includes( | ||
| 'Automatic merge failed; fix conflicts and then commit the result.', | ||
| ) | ||
| ) { | ||
| console.warn( | ||
| 'Merge conflict encountered. Continuing script execution.', | ||
| ); | ||
| } else { | ||
| console.error(`Error: ${error.message}`); | ||
| process.exit(1); | ||
| } | ||
| } | ||
|
|
||
| await exec('git add .'); | ||
| await exec('git restore --source origin/main .'); | ||
| console.log('Executed: it restore --source origin/main .'); | ||
|
|
||
| await exec('git checkout origin/main -- .'); | ||
| console.log('Executed: git checkout origin/main -- .'); | ||
|
|
||
| await exec('git checkout origin/stable -- CHANGELOG.md'); | ||
| console.log('Executed: git checkout origin/stable -- CHANGELOG.md'); | ||
|
|
||
| // Execute mobile-specific commands if REPO is 'mobile' | ||
| if (process.env.REPO === 'mobile') { | ||
| console.log('Executing mobile-specific commands...'); | ||
|
|
||
| await exec('git checkout origin/stable -- bitrise.yml'); | ||
| console.log('Executed: git checkout origin/stable -- bitrise.yml'); | ||
|
|
||
| await exec('git checkout origin/stable -- android/app/build.gradle'); | ||
| console.log('Executed: git checkout origin/stable -- android/app/build.gradle'); | ||
|
|
||
| await exec('git checkout origin/stable -- ios/MetaMask.xcodeproj/project.pbxproj'); | ||
| console.log('Executed: git checkout origin/stable -- ios/MetaMask.xcodeproj/project.pbxproj'); | ||
|
|
||
| await exec('git checkout origin/stable -- package.json'); | ||
| console.log('Executed: git checkout origin/stable -- package.json'); | ||
| } | ||
| // Execute extension-specific commands if REPO is 'extension' | ||
| else if (process.env.REPO === 'extension') { | ||
| console.log('Executing extension-specific commands...'); | ||
|
|
||
| const { stdout: packageJsonContent } = await exec( | ||
| 'git show origin/master:package.json', | ||
| ); | ||
| const packageJson = JSON.parse(packageJsonContent); | ||
| const packageVersion = packageJson.version; | ||
|
|
||
| await exec(`yarn version "${packageVersion}"`); | ||
| console.log('Executed: yarn version'); | ||
| } | ||
| // If REPO is not set or has an invalid value, skip both | ||
| else { | ||
| console.log('REPO environment variable not set or invalid. Skipping mobile/extension specific commands.'); | ||
| } | ||
|
|
||
| await exec('git add .'); | ||
| console.log('Executed: git add .'); | ||
|
|
||
| try { | ||
| // Check if there are any changes to commit | ||
| const { stdout: status } = await exec('git status --porcelain'); | ||
| if (!status.trim()) { | ||
| console.log('No changes to commit, skipping commit step'); | ||
| return; | ||
| } | ||
|
|
||
| await exec(`git commit -m "Merge origin/main into ${branchName}" --no-verify`); | ||
| console.log('Executed: git commit'); | ||
| } catch (error) { | ||
| console.error(`Error: ${error.message}`); | ||
| process.exit(1); | ||
| } | ||
|
|
||
| console.log(`Your local ${branchName} branch is now ready to become a PR.`); | ||
|
|
||
| // Push the branch if CREATE_BRANCH is true | ||
| if (shouldPushBranch) { | ||
| try { | ||
| console.log(`Checking if branch ${branchName} exists remotely...`); | ||
| const { stdout: remoteBranches } = await exec('git ls-remote --heads origin'); | ||
| const branchExists = remoteBranches.includes(`refs/heads/${branchName}`); | ||
|
|
||
| if (branchExists) { | ||
| console.log(`Branch ${branchName} exists remotely, updating...`); | ||
| await exec(`git push origin ${branchName}`); | ||
| } else { | ||
| console.log(`Branch ${branchName} does not exist remotely, creating...`); | ||
| await exec(`git push --set-upstream origin ${branchName}`); | ||
| } | ||
| console.log(`Successfully pushed branch ${branchName} to remote`); | ||
| } catch (error) { | ||
| console.error(`Error pushing branch: ${error.message}`); | ||
| process.exit(1); | ||
| } | ||
| } else { | ||
| console.log('You likely now need to do `git push --force`'); | ||
| } | ||
| } catch (error) { | ||
| console.error(`Error: ${error.message}`); | ||
| process.exit(1); | ||
| } | ||
| } | ||
|
|
||
| runGitCommands(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| name: Stable Sync | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| inputs: | ||
| semver-version: | ||
| required: true | ||
| type: string | ||
| description: 'The semantic version to use for the sync (e.g., x.x.x)' | ||
| repo-type: | ||
| required: false | ||
| type: choice | ||
| description: 'Type of repository (mobile or extension)' | ||
| options: | ||
| - mobile | ||
| - extension | ||
| default: 'mobile' | ||
| workflow_call: | ||
| inputs: | ||
| semver-version: | ||
| required: true | ||
| type: string | ||
| description: 'The semantic version to use for the sync (e.g., x.x.x)' | ||
| repo-type: | ||
| required: false | ||
| type: string | ||
| description: 'Type of repository (mobile or extension)' | ||
| default: 'mobile' | ||
|
|
||
| jobs: | ||
| stable-sync: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 | ||
|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '18' | ||
|
|
||
| - name: Check if PR exists | ||
| id: check-pr | ||
| uses: actions/github-script@v7 | ||
| with: | ||
| script: | | ||
| const { data: prs } = await github.rest.pulls.list({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| head: `${context.repo.owner}:stable-main-${process.env.SEMVER_VERSION}`, | ||
| base: 'main' | ||
| }); | ||
| return prs.length > 0; | ||
| env: | ||
| SEMVER_VERSION: ${{ inputs.semver-version }} | ||
|
|
||
| - name: Set Git user and email | ||
| run: | | ||
| git config --global user.name "metamaskbot" | ||
| git config --global user.email "metamaskbot@users.noreply.github.com" | ||
|
|
||
| - name: Run stable sync | ||
| id: run-stable-sync | ||
| # if: steps.check-pr.outputs.result != 'true' | ||
| env: | ||
| CREATE_BRANCH: 'false' # let the script handle the branch creation | ||
| REPO: ${{ inputs.repo-type }} # Default to 'mobile' if not specified | ||
| run: | | ||
| node .github/scripts/stable-sync.js "stable-main-${{ inputs.semver-version }}" | ||
| # Check if branch exists remotely | ||
| BRANCH_NAME="stable-main-${{ inputs.semver-version }}" | ||
| if git ls-remote --heads origin "$BRANCH_NAME" | grep -q "$BRANCH_NAME"; then | ||
| git pull --rebase | ||
| echo "Branch $BRANCH_NAME exists remotely, pushing normally" | ||
| git push origin "$BRANCH_NAME" --force | ||
| else | ||
| echo "Branch $BRANCH_NAME doesn't exist remotely, pushing with --set-upstream" | ||
| git push --set-upstream origin "$BRANCH_NAME" | ||
| fi | ||
|
|
||
| - name: Create Pull Request | ||
| if: steps.check-pr.outputs.result != 'true' | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| BRANCH_NAME: stable-main-${{ inputs.semver-version }} | ||
| VERSION: ${{ inputs.semver-version }} | ||
| run: | | ||
| # Create PR using GitHub CLI | ||
| gh pr create \ | ||
| --title "chore: sync stable to main for version $VERSION" \ | ||
| --body "This PR syncs the stable branch to main for version $VERSION. | ||
|
|
||
| *Synchronization Process:* | ||
|
|
||
| - Fetches the latest changes from the remote repository | ||
| - Resets the branch to match the stable branch | ||
| - Attempts to merge changes from main into the branch | ||
| - Handles merge conflicts if they occur | ||
|
|
||
| *File Preservation:* | ||
|
|
||
| Preserves specific files from the stable branch: | ||
| - CHANGELOG.md | ||
| - bitrise.yml | ||
| - android/app/build.gradle | ||
| - ios/MetaMask.xcodeproj/project.pbxproj | ||
| - package.json | ||
|
|
||
| Indicates the next version candidate of main to $VERSION" \ | ||
| --base main \ | ||
| --head "$BRANCH_NAME" | ||
| #--label "sync" \ | ||
| #--label "stable" | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.