Github Actions is Github’s free automated build implementation, especially for continuous integration and continuous delivery scenarios, with the ability to automate many different tasks, such as build, test, and deploy.
A brief introduction
Github provides a marketplace for developers to submit or reference acitons written by others. So a lot of the time when developers are using Github Actions, they are actually choosing and combining Actions in the marketplace. Of course, there are pros and cons to this, which we’ll talk about later.
To use Github Actions in the Github repository, you first need to create a directory. Github /workflows/ and then create different.yml files in the workflows folder to respond to or execute different events. Git push request git push request git push request
name: GitHub Actions Demo
on: [push]
jobs:
Explore-GitHub-Actions:
runs-on: ubuntu-latest
steps:
- run: echo 🎉 The job was automatically triggered by a ${{ github.event_name }} event."
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
- run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
- name: Check out repository code
uses: actions/checkout@v2
- run: echo The "💡 ${{ github.repository }} repository has been cloned to the runner."
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
- name: List files in the repository
run: | ls ${{ github.workspace }} - run: echo "🍏 This job's status is ${{ job.status }}."
Copy the code
Github Doc is a simple workflow yML file for Action.
- Name: This represents the name of the workflow file, which will be displayed as a name in Github’s Actions TAB;
- on: This will trigger the event name of the workflow, which can contain a list of events, such as the one being listened for here
push
; - Jobs: Each workflow may contain one or more Jobs. In this case, only one is used to represent different tasks.
- Explore-GitHub-Actions: This is the job ID, which you can name as you like, and which will be displayed during the execution of the action;
- runs-o: Jobs needs to run on a virtual machine, which is used here
ubuntu-latest
Of course you can use itwindows-latest
ormacos-latest
; - Steps: Each Job can divide the content that needs to be performed into steps;
- run: used to provide execution commands, such as the one used here
echo
Print logs; - Name: The name in steps is optional and is mainly used for marking in the log;
- uses: Use some official or third party actions, such as official here
actions/checkout@v2
, it checks out our repO, and then the workflow can directly access the files in the REPO;
After the corresponding.github/workflows/ci.yml file is added to the GitHub repository, the automatic execution of actions can be triggered for each subsequent push to achieve sustainable automatic integration and build capabilities.
Build Flutter and publish to Github Release
Github Actions can be used to build Flutter and publish APK to Github Release. The github action script used in the gsy_github_app_flutter project is shown below:
name: CI
on:
push:
branches:
- master
tags:
- The '*'
pull_request:
paths-ignore:
- '**/*.md'
- '**/*.txt'
- '**/*.png'
- '**/*.jpg'
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v2
with:
distribution: 'zulu'
java-version: 11
- uses: subosito/flutter-action@v1
with:
flutter-version: '2.8.1'
- uses: finnp/create-file-action@master
env:
FILE_NAME: lib/common/config/ignoreConfig.dart
FILE_DATA: class NetConfig { static const CLIENT_ID = "${{ secrets.CLIENT_ID }}"; static const CLIENT_SECRET = "${{ secrets.CLIENT_SECRET }}";}
- run: flutter pub get
- run: flutter build apk --release --target-platform=android-arm64 --no-shrink
apk:
name: Generate APK
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup JDK
uses: actions/setup-java@v2
with:
distribution: 'zulu'
java-version: 8
- uses: subosito/flutter-action@v1
with:
flutter-version: '2.5.3'
- uses: finnp/create-file-action@master
env:
FILE_NAME: lib/common/config/ignoreConfig.dart
FILE_DATA: class NetConfig { static const CLIENT_ID = "${{ secrets.CLIENT_ID }}"; static const CLIENT_SECRET = "${{ secrets.CLIENT_SECRET }}";}
- run: flutter pub get
- run: flutter build apk --release --target-platform=android-arm64 --no-shrink
- name: Upload APK
uses: actions/upload-artifact@v2
with:
name: apk
path: build/app/outputs/apk/release/app-release.apk
release:
name: Release APK
needs: apk
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
steps:
- name: Download APK from build
uses: actions/download-artifact@v2
with:
name: apk
- name: Display structure of downloaded files
run: ls -R
- name: Create Release
id: create_release
uses: The actions/[email protected]
env:
GITHUB_TOKEN: The ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: The ${{ github.ref }}
release_name: The ${{ github.ref }}
- name: Upload Release APK
id: upload_release_asset
uses: The actions/[email protected]
env:
GITHUB_TOKEN: The ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: The ${{ steps.create_release.outputs.upload_url }}
asset_path: ./app-release.apk
asset_name: app-release.apk
asset_content_type: application/zip
Copy the code
Based on the above script, you can first see:
-
In the push event we specify that we only listen for the master branch and tags related commits;
-
Then the.md,.text and pictures will be ignored in the pull_request event, that is, the submission of this part of content will not trigger action, depending on your own needs;
-
The push or pull_request will be executed to the Build event, running on the Ubuntu-latest VM, and then using the Actions /checkout@v2 checkout code.
-
Next, use Actions /setup-java@v2 to configure the Java environment. Here, Zulu OpenJDK version 11 is used. The table below shows the optional Java types supported by Setup-Java.
Keyword Distribution Official site License temurin
Eclipse Temurin Link Link zulu
Zulu OpenJDK Link Link adopt
oradopt-hotspot
Adopt OpenJDK Hotspot Link Link adopt-openj9
Adopt OpenJDK OpenJ9 Link Link liberica
Liberica JDK Link Link microsoft
Microsoft Build of OpenJDK Link Link -
Subosito /flutter-action@v1 is used to configure the flutter environment, specifying the flutter version directly via the flutter-version: ‘2.8.1’.
-
The gsy_github_app_FLUTTER project has a configuration file that needs to be manually created by users based on their ID and SECRET. So create-file-action creates the file and enters the content;
-
In the input content above, there is a parameter of secrets. XXX, as shown in the following figure, you can add the corresponding content in the secrets of Settings, because you need to configure some of your own key information into the action during construction. You can read it in action via secrets. XXX.
-
Then, after the environment is configured, you can execute the flutter pub GET and flutter Build APK to perform the build.
After completing the logic of the Build task, you can see that there is an APK task under the Build task, which is basically the same as the Build task, except that:
- One more
if: startsWith(github.ref, 'refs/tags/')
, that is, the task will be triggered only when the tag exists. - One more
actions/upload-artifact@v2
Used to buildbuild/app/outputs/apk/release/app-release.apk
Upload and wait for use in the Release task;
After completing the APK task, we enter the Release task, which is also specified by if to run only on tag commits:
- The task will pass first
actions/download-artifact@v2
Download the apK you just uploaded; - And then it goes through
The actions/[email protected]
Create a release version, which is used heresecrets.GITHUB_TOKEN
Is the official built-in secrets, we can directly use it; - At last,
The actions/[email protected]
Upload the APK to the release you just created, and from there you complete the action publishing process;
As you can see, the whole process is actually combining different actions, which can be flexibly configured to build logic. For example, if your project is a pure Android SDK project, you can also use the following script for release management:
name: CI
on:
push:
branches:
- master
paths-ignore:
- '.idea/**'
- '.gitattributes'
- '.github/**.json'
- '.gitignore'
- '.gitmodules'
- '**.md'
- '**/*.txt'
- '**/*.png'
- '**/*.jpg'
- 'LICENSE'
- 'NOTICE'
pull_request:
paths-ignore:
- '.idea/**'
- '.gitattributes'
- '.github/**.json'
- '.gitignore'
- '.gitmodules'
- '**.md'
- '**/*.txt'
- '**/*.png'
- '**/*.jpg'
- 'LICENSE'
- 'NOTICE'
jobs:
publish:
name: Publish to MavenLocal
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: 17
- uses: gradle/gradle-build-action@v2
with:
arguments: publishToMavenLocal
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: 17
- uses: gradle/gradle-build-action@v2
with:
arguments: app:assembleDebug
Copy the code
Of course, if you need to package iOS, you will need to use macOS-latest environment and configure the relevant developer certificate. This process can be uncomfortable, as can be seen in the “Flutter Setup iOS Command Line Service Packaging Process”.
Third, privacy security issues
Finally, Github Actions have been known to leak sensitive data, such as Github tokens. For example, the script above requires a secret key to perform tasks. If you use a third party action that gets your key and does something “illegal” during execution, you can have an abnormal leak problem.
It is generally recommended that you checkout unofficial script implementations to see if they are secure, but since tag and branch can be modified, it is recommended that you do not use the @ branch or tag, but instead use the checkout corresponding commit hash. This will help you check if the script is secure when you use it.
In addition, for example, some people mentioned the pull_request malicious attack to obtain corresponding privacy:
-
Fork a public code base that is using GitHub Actions;
-
2. Create a pull request based on the project.
-
Create a malicious Actions workflow using the pull_request_target event and commit to the fork library separately.
-
Update the pull request from the base branch in Step 2 to the COMMIT hash in Step 3.
The malicious Actions workflow is then run and sensitive execution data is retrieved from the target Repos, at which point the attacker will have write access to the target repository, in addition to any services associated with the repository via GitHub.
So while GitHub actions are convenient, you need to be careful about security if you’re doing it for business reasons.