Skip to content
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

feat: add workflow for projects to sync with new template versions #86

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 168 additions & 0 deletions .github/project-workflows/sync-with-template.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
# 🔗 Links:
# Source file: https://github.com/rootstrap/react-native-template/blob/master/.github/project-workflows/sync-with-template.yml

# ✍️ Description:
# This workflow is used to keep the project up to date with the latest version of the template.

# 🚨 GITHUB SECRETS REQUIRED:
# - UPDATE_FROM_TEMPLATE_PAT: A fine-grained Personal Access Token.
# This token is used to access the project repository and create the Pull Request.
# You can generate one from here: https://github.com/settings/tokens?type=beta
# Set the Repository access to "Only select repositories" and select the project repository.
# Set the following Repo permissions:
# - Contents: Read & write (to commit and push the update branch to the project repository)
# - Metadata: Read-only (mandatory by GitHub)
# - Pull requests: Read & write (to create the Pull Request in the project repository)
# - Workflows: Read and write (to create, update and delete workflows in the project repository)
# Make sure to add it to the repo secrets with the name UPDATE_FROM_TEMPLATE_PAT:
# - Go to Repository Settings > Secrets and variables > Actions > New repository secret
# - Name: UPDATE_FROM_TEMPLATE_PAT
# - Value: The Personal Access Token you created

# ℹ️ Environment variables:
# - TEMPLATE_REPOSITORY: Repository to sync with
# - DIFF_EXCLUDED_ROUTES: List of files or directories to exclude from the diff.
# Any changes in these files or directories will be ignored
# and won't be incorporated to the Pull Request.

name: 🔄 Sync with template

on:
schedule:
- cron: '0 12 * * *' # Everyday at 12:00 UTC
workflow_dispatch:

env:
TEMPLATE_REPOSITORY: rootstrap/react-native-template
DIFF_EXCLUDED_ROUTES: |
cli
docs
ios
android
.github/workflows/deploy-docs.yml
.github/workflows/new-template-version.yml
.github/workflows/upstream-to-pr.yml
README-project.md

jobs:
sync:
runs-on: ubuntu-latest
permissions:
actions: write
contents: read

steps:
- name: Check if Personal Access Token exists
env:
PAT: ${{ secrets.UPDATE_FROM_TEMPLATE_PAT }}
if: env.PAT == ''
run: |
echo "UPDATE_FROM_TEMPLATE_PAT secret not found. Please create a fine-grained Personal Access Token following the instructions in the workflow file."
exit 1
- name: Checkout project repository
uses: actions/checkout@v3
with:
fetch-depth: 0
path: project
token: ${{ secrets.UPDATE_FROM_TEMPLATE_PAT }}
- name: Get template version used in project from package.json
run: |
echo "PROJECT_TEMPLATE_VERSION=v$(jq -r 'if has("rsMetadata") then .rsMetadata.templateVersion else .osMetadata.initVersion end' project/package.json | sed 's/^.*@//')" >> $GITHUB_ENV
- name: Get latest release of template from GitHub
run: |
echo "TEMPLATE_LATEST_VERSION=$(curl -s https://api.github.com/repos/${{ env.TEMPLATE_REPOSITORY }}/releases/latest | jq '.tag_name' | sed 's/\"//g')" >> $GITHUB_ENV
- name: Check if the template is up to date
run: |
if [[ $TEMPLATE_LATEST_VERSION == $PROJECT_TEMPLATE_VERSION ]]; then
echo "Template is up to date"
cd project
gh run cancel ${{ github.run_id }}
gh run watch ${{ github.run_id }}
fi
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Check if branch already exists
run: |
cd project
git fetch origin
BRANCH_NAME=update-template-${{ env.TEMPLATE_LATEST_VERSION }}
echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV
git branch -r | grep -q "origin/$BRANCH_NAME" && echo "BRANCH_EXISTS=true" >> $GITHUB_ENV || echo "BRANCH_EXISTS=false" >> $GITHUB_ENV
- name: Check if PR already exists
run: |
cd project
prs=$(gh pr list \
--head "$BRANCH_NAME" \
--json title \
--jq 'length')
if ((prs > 0)); then
echo "PR_EXISTS=true" >> $GITHUB_ENV
else
echo "PR_EXISTS=false" >> $GITHUB_ENV
fi
env:
GITHUB_TOKEN: ${{ secrets.UPDATE_FROM_TEMPLATE_PAT }}
- name: Install dependencies
if: ${{ env.BRANCH_EXISTS == 'false' }}
run: |
sudo apt install wiggle
- name: Checkout latest release of template
if: ${{ env.BRANCH_EXISTS == 'false' }}
uses: actions/checkout@v3
with:
repository: ${{ env.TEMPLATE_REPOSITORY }}
ref: ${{ env.TEMPLATE_LATEST_VERSION }}
fetch-depth: 0
path: react-native-template
- name: Get diff between latest release and used release
if: ${{ env.BRANCH_EXISTS == 'false' }}
run: |
EXCLUDED_ROUTES=""
for route in $DIFF_EXCLUDED_ROUTES; do
EXCLUDED_ROUTES="$EXCLUDED_ROUTES ':(exclude)$route'"
done
cd react-native-template
git diff ${{ env.PROJECT_TEMPLATE_VERSION }} -- . $(echo $EXCLUDED_ROUTES | xargs) > ../update.patch
- name: Update template version in package.json
if: ${{ env.BRANCH_EXISTS == 'false' }}
run: |
cd project
jq 'del(.osMetadata)' package.json > tmp.json && mv tmp.json package.json
PLAIN_VERSION=${TEMPLATE_LATEST_VERSION#v}
jq --arg version $PLAIN_VERSION '.rsMetadata.templateVersion = $version' package.json > tmp.json && mv tmp.json package.json
- name: Apply diff to project repository
if: ${{ env.BRANCH_EXISTS == 'false' }}
run: |
cd project
git apply --reject ../update.patch
continue-on-error: true
- name: Solve conflicts with wiggle
if: ${{ env.BRANCH_EXISTS == 'false' }}
run: |
cd project
find . -iname '*.rej' -exec sh -c 'printf "%s\n" "${0%.*}"' {} ';' | xargs -I _ wiggle --replace --merge _ _.rej
continue-on-error: true
- name: Remove wiggle's backup and .rej files
if: ${{ env.BRANCH_EXISTS == 'false' }}
run: |
cd project
find . -not -path './.git/*' -type f -name '*.porig' -delete
find . -not -path './.git/*' -type f -name '*.rej' -delete
- name: Commit and push changes to the update branch
if: ${{ env.BRANCH_EXISTS == 'false' }}
run: |
cd project
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --global user.name "github-actions[bot]"
git checkout -b ${{ env.BRANCH_NAME }}
git add .
git commit -m "chore: update template to ${{ env.TEMPLATE_LATEST_VERSION }}"
git push origin ${{ env.BRANCH_NAME }}
echo "BRANCH_EXISTS=true" >> $GITHUB_ENV
- name: 🎉 Create PR with changes
if: ${{ env.BRANCH_EXISTS == 'true' && env.PR_EXISTS == 'false' }}
run: |
cd project
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 }}
env:
GITHUB_TOKEN: ${{ secrets.UPDATE_FROM_TEMPLATE_PAT }}
17 changes: 14 additions & 3 deletions cli/setup-project.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ const removeUnrelatedFiles = () => {
]);
};

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

const packageJson = fs.readJsonSync(packageJsonPath);
packageJson.osMetadata = { initVersion: packageJson.version };
packageJson.rsMetadata = { templateVersion: packageJson.version };
packageJson.version = '0.0.1';
packageJson.name = projectName?.toLowerCase();
packageJson.repository = {
Expand All @@ -54,7 +54,7 @@ const updatePackageJson = async (projectName) => {
const appReleaseScript = packageJson.scripts['app-release'];
packageJson.scripts['app-release'] = appReleaseScript.replace(
'template',
projectName
projectName,
);
fs.writeJsonSync(packageJsonPath, packageJson, { spaces: 2 });
};
Expand Down Expand Up @@ -145,6 +145,17 @@ const updateGitHubWorkflows = (projectName) => {
],
},
]);

// Remove upstream update workflow, intended to be used only in the template repository
projectFilesManager.removeFiles(['.github/workflows/upstream-to-pr.yml']);

// Enable sync with template workflow
projectFilesManager.renameFiles([
{
oldFileName: '.github/project-workflows/sync-with-template.yml',
newFileName: '.github/workflows/sync-with-template.yml',
},
]);
};

const updateProjectReadme = (projectName) => {
Expand Down
6 changes: 5 additions & 1 deletion docs/src/content/docs/ci-cd/workflows-references.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ head:

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

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

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.

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

<CodeBlock file=".github/workflows/e2e-android-eas-build.yml" />

### ⚙️ Sync with template

<CodeBlock file=".github/project-workflows/sync-with-template.yml" />
6 changes: 3 additions & 3 deletions docs/src/content/docs/guides/upgrading-deps.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import CodeBlock from '../../../components/code.astro';
:::note
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.

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.
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.
:::

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

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

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.
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.

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

Expand All @@ -38,7 +38,7 @@ pnpm start --cc ## start the server
```

:::info
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.
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.

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."
:::
Expand Down
Loading