Skip to content

Commit ccf8fd0

Browse files
committed
feat: add workflow for projects to sync with new template versions
1 parent f50b850 commit ccf8fd0

File tree

4 files changed

+190
-7
lines changed

4 files changed

+190
-7
lines changed
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
# 🔗 Links:
2+
# Source file: https://github.com/rootstrap/react-native-template/blob/master/.github/project-workflows/sync-with-template.yml
3+
4+
# ✍️ Description:
5+
# This workflow is used to keep the project up to date with the latest version of the template.
6+
7+
# 🚨 GITHUB SECRETS REQUIRED:
8+
# - UPDATE_FROM_TEMPLATE_PAT: A fine-grained Personal Access Token.
9+
# This token is used to access the project repository and create the Pull Request.
10+
# You can generate one from here: https://github.com/settings/tokens?type=beta
11+
# Set the Repository access to "Only select repositories" and select the project repository.
12+
# Set the following Repo permissions:
13+
# - Contents: Read & write (to commit and push the update branch to the project repository)
14+
# - Metadata: Read-only (mandatory by GitHub)
15+
# - Pull requests: Read & write (to create the Pull Request in the project repository)
16+
# - Workflows: Read and write (to create, update and delete workflows in the project repository)
17+
# Make sure to add it to the repo secrets with the name UPDATE_FROM_TEMPLATE_PAT:
18+
# - Go to Repository Settings > Secrets and variables > Actions > New repository secret
19+
# - Name: UPDATE_FROM_TEMPLATE_PAT
20+
# - Value: The Personal Access Token you created
21+
22+
# ℹ️ Environment variables:
23+
# - TEMPLATE_REPOSITORY: Repository to sync with
24+
# - DIFF_EXCLUDED_ROUTES: List of files or directories to exclude from the diff.
25+
# Any changes in these files or directories will be ignored
26+
# and won't be incorporated to the Pull Request.
27+
28+
name: 🔄 Sync with template
29+
30+
on:
31+
schedule:
32+
- cron: '0 12 * * *' # Everyday at 12:00 UTC
33+
workflow_dispatch:
34+
35+
env:
36+
TEMPLATE_REPOSITORY: rootstrap/react-native-template
37+
DIFF_EXCLUDED_ROUTES: |
38+
cli
39+
docs
40+
ios
41+
android
42+
.github/workflows/deploy-docs.yml
43+
.github/workflows/new-template-version.yml
44+
.github/workflows/upstream-to-pr.yml
45+
README-project.md
46+
47+
jobs:
48+
sync:
49+
runs-on: ubuntu-latest
50+
permissions:
51+
actions: write
52+
contents: read
53+
54+
steps:
55+
- name: Check if Personal Access Token exists
56+
env:
57+
PAT: ${{ secrets.UPDATE_FROM_TEMPLATE_PAT }}
58+
if: env.PAT == ''
59+
run: |
60+
echo "UPDATE_FROM_TEMPLATE_PAT secret not found. Please create a fine-grained Personal Access Token following the instructions in the workflow file."
61+
exit 1
62+
- name: Checkout project repository
63+
uses: actions/checkout@v3
64+
with:
65+
fetch-depth: 0
66+
path: project
67+
token: ${{ secrets.UPDATE_FROM_TEMPLATE_PAT }}
68+
- name: Get template version used in project from package.json
69+
run: |
70+
echo "PROJECT_TEMPLATE_VERSION=v$(jq -r 'if has("rsMetadata") then .rsMetadata.templateVersion else .osMetadata.initVersion end' project/package.json | sed 's/^.*@//')" >> $GITHUB_ENV
71+
- name: Get latest release of template from GitHub
72+
run: |
73+
echo "TEMPLATE_LATEST_VERSION=$(curl -s https://api.github.com/repos/${{ env.TEMPLATE_REPOSITORY }}/releases/latest | jq '.tag_name' | sed 's/\"//g')" >> $GITHUB_ENV
74+
- name: Check if the template is up to date
75+
run: |
76+
if [[ $TEMPLATE_LATEST_VERSION == $PROJECT_TEMPLATE_VERSION ]]; then
77+
echo "Template is up to date"
78+
cd project
79+
gh run cancel ${{ github.run_id }}
80+
gh run watch ${{ github.run_id }}
81+
fi
82+
env:
83+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
84+
- name: Check if branch already exists
85+
run: |
86+
cd project
87+
git fetch origin
88+
BRANCH_NAME=update-template-${{ env.TEMPLATE_LATEST_VERSION }}
89+
echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV
90+
git branch -r | grep -q "origin/$BRANCH_NAME" && echo "BRANCH_EXISTS=true" >> $GITHUB_ENV || echo "BRANCH_EXISTS=false" >> $GITHUB_ENV
91+
- name: Check if PR already exists
92+
run: |
93+
cd project
94+
prs=$(gh pr list \
95+
--head "$BRANCH_NAME" \
96+
--json title \
97+
--jq 'length')
98+
if ((prs > 0)); then
99+
echo "PR_EXISTS=true" >> $GITHUB_ENV
100+
else
101+
echo "PR_EXISTS=false" >> $GITHUB_ENV
102+
fi
103+
env:
104+
GITHUB_TOKEN: ${{ secrets.UPDATE_FROM_TEMPLATE_PAT }}
105+
- name: Install dependencies
106+
if: ${{ env.BRANCH_EXISTS == 'false' }}
107+
run: |
108+
sudo apt install wiggle
109+
- name: Checkout latest release of template
110+
if: ${{ env.BRANCH_EXISTS == 'false' }}
111+
uses: actions/checkout@v3
112+
with:
113+
repository: ${{ env.TEMPLATE_REPOSITORY }}
114+
ref: ${{ env.TEMPLATE_LATEST_VERSION }}
115+
fetch-depth: 0
116+
path: react-native-template
117+
- name: Get diff between latest release and used release
118+
if: ${{ env.BRANCH_EXISTS == 'false' }}
119+
run: |
120+
EXCLUDED_ROUTES=""
121+
for route in $DIFF_EXCLUDED_ROUTES; do
122+
EXCLUDED_ROUTES="$EXCLUDED_ROUTES ':(exclude)$route'"
123+
done
124+
cd react-native-template
125+
git diff ${{ env.PROJECT_TEMPLATE_VERSION }} -- . $(echo $EXCLUDED_ROUTES | xargs) > ../update.patch
126+
- name: Update template version in package.json
127+
if: ${{ env.BRANCH_EXISTS == 'false' }}
128+
run: |
129+
cd project
130+
jq 'del(.osMetadata)' package.json > tmp.json && mv tmp.json package.json
131+
PLAIN_VERSION=${TEMPLATE_LATEST_VERSION#v}
132+
jq --arg version $PLAIN_VERSION '.rsMetadata.templateVersion = $version' package.json > tmp.json && mv tmp.json package.json
133+
- name: Apply diff to project repository
134+
if: ${{ env.BRANCH_EXISTS == 'false' }}
135+
run: |
136+
cd project
137+
git apply --reject ../update.patch
138+
continue-on-error: true
139+
- name: Solve conflicts with wiggle
140+
if: ${{ env.BRANCH_EXISTS == 'false' }}
141+
run: |
142+
cd project
143+
find . -iname '*.rej' -exec sh -c 'printf "%s\n" "${0%.*}"' {} ';' | xargs -I _ wiggle --replace --merge _ _.rej
144+
continue-on-error: true
145+
- name: Remove wiggle's backup and .rej files
146+
if: ${{ env.BRANCH_EXISTS == 'false' }}
147+
run: |
148+
cd project
149+
find . -not -path './.git/*' -type f -name '*.porig' -delete
150+
find . -not -path './.git/*' -type f -name '*.rej' -delete
151+
- name: Commit and push changes to the update branch
152+
if: ${{ env.BRANCH_EXISTS == 'false' }}
153+
run: |
154+
cd project
155+
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
156+
git config --global user.name "github-actions[bot]"
157+
git checkout -b ${{ env.BRANCH_NAME }}
158+
git add .
159+
git commit -m "chore: update template to ${{ env.TEMPLATE_LATEST_VERSION }}"
160+
git push origin ${{ env.BRANCH_NAME }}
161+
echo "BRANCH_EXISTS=true" >> $GITHUB_ENV
162+
- name: 🎉 Create PR with changes
163+
if: ${{ env.BRANCH_EXISTS == 'true' && env.PR_EXISTS == 'false' }}
164+
run: |
165+
cd project
166+
gh pr create --title "chore: update template to ${{ env.TEMPLATE_LATEST_VERSION }}" --body "Integrating latest changes from [rootstrap/react-native-template@${{ env.TEMPLATE_LATEST_VERSION }}](https://github.com/rootstrap/react-native-template/releases/tag/${{ env.TEMPLATE_LATEST_VERSION }})" --head ${{ env.BRANCH_NAME }}
167+
env:
168+
GITHUB_TOKEN: ${{ secrets.UPDATE_FROM_TEMPLATE_PAT }}

cli/setup-project.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,13 @@ const removeUnrelatedFiles = () => {
3737
]);
3838
};
3939

40-
// Update package.json infos, name and set version to 0.0.1 + add initial version to osMetadata
40+
// Update package.json infos, name and set version to 0.0.1 + add initial version to rsMetadata
4141
const updatePackageJson = async (projectName) => {
4242
const packageJsonPath =
4343
projectFilesManager.getAbsoluteFilePath('package.json');
4444

4545
const packageJson = fs.readJsonSync(packageJsonPath);
46-
packageJson.osMetadata = { initVersion: packageJson.version };
46+
packageJson.rsMetadata = { templateVersion: packageJson.version };
4747
packageJson.version = '0.0.1';
4848
packageJson.name = projectName?.toLowerCase();
4949
packageJson.repository = {
@@ -54,7 +54,7 @@ const updatePackageJson = async (projectName) => {
5454
const appReleaseScript = packageJson.scripts['app-release'];
5555
packageJson.scripts['app-release'] = appReleaseScript.replace(
5656
'template',
57-
projectName
57+
projectName,
5858
);
5959
fs.writeJsonSync(packageJsonPath, packageJson, { spaces: 2 });
6060
};
@@ -145,6 +145,17 @@ const updateGitHubWorkflows = (projectName) => {
145145
],
146146
},
147147
]);
148+
149+
// Remove upstream update workflow, intended to be used only in the template repository
150+
projectFilesManager.removeFiles(['.github/workflows/upstream-to-pr.yml']);
151+
152+
// Enable sync with template workflow
153+
projectFilesManager.renameFiles([
154+
{
155+
oldFileName: '.github/project-workflows/sync-with-template.yml',
156+
newFileName: '.github/workflows/sync-with-template.yml',
157+
},
158+
]);
148159
};
149160

150161
const updateProjectReadme = (projectName) => {

docs/src/content/docs/ci-cd/workflows-references.mdx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ head:
88

99
import CodeBlock from '../../../components/code.astro';
1010

11-
The starter comes with over 10 GitHub Actions workflows that help you automate the process of checking, testing, releasing, and much more.
11+
The template comes with over 10 GitHub Actions workflows that help you automate the process of checking, testing, releasing, and much more.
1212

1313
All those workflows are self-documented and contain all details directly inside the workflow file as comments. This approach makes it easier to understand what each workflow does and how to use it without having to go back and forth between the documentation and the workflow file.
1414

@@ -71,3 +71,7 @@ All actions are located in the `.github/actions` folder, and here is the complet
7171
### ⚙️ E2E Test for Android using EAS Build
7272

7373
<CodeBlock file=".github/workflows/e2e-android-eas-build.yml" />
74+
75+
### ⚙️ Sync with template
76+
77+
<CodeBlock file=".github/project-workflows/sync-with-template.yml" />

docs/src/content/docs/guides/upgrading-deps.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import CodeBlock from '../../../components/code.astro';
1111
:::note
1212
Please note that this guide is intended for updating your project dependencies only, and it does not ensure that your project will be in sync with the latest version of the starter.
1313

14-
To take advantage of the latest improvements in the starter project, you will need to compare your `osMetadata.initVersion` with the latest release on GitHub, and manually apply any necessary changes to your project.
14+
To take advantage of the latest improvements in the Template project, you will need to compare your `rsMetadata.templateVersion` with the latest release on GitHub, and manually apply any necessary changes to your project.
1515
:::
1616

1717
## Easy way 🚀
@@ -20,7 +20,7 @@ Upgrading a React Native project to the latest version can be a challenging task
2020

2121
To update most of the dependencies that come with the starter, you can follow these simple steps:
2222

23-
First, go to GitHub and compare your `osMetadata.initVersion` in your `package.json` with the latest release. Check if the `package.json` has been updated. Then, copy the new dependencies and devDependencies versions and paste them into your package.json file.
23+
First, go to GitHub and compare your `rsMetadata.templateVersion` in your `package.json` with the latest release. Check if the `package.json` has been updated. Then, copy the new dependencies and devDependencies versions and paste them into your package.json file.
2424

2525
Finally, run the following commands to make sur everything is working as expected:
2626

@@ -38,7 +38,7 @@ pnpm start --cc ## start the server
3838
```
3939

4040
:::info
41-
If your starter version does not have the `osMetadata.initVersion` property, don't worry. Simply follow the steps in the rest of this guide to upgrade your project.
41+
If your Template version does not have the `rsMetadata.templateVersion` property, don't worry. Simply follow the steps in the rest of this guide to upgrade your project.
4242

4343
Moreover, if you have added new dependencies to your project (which is common for most projects), the remaining sections of this guide will also assist you in upgrading your project's dependencies."
4444
:::

0 commit comments

Comments
 (0)