mirror of
https://github.com/actions/runner.git
synced 2025-12-10 12:36:23 +00:00
Compare commits
10 Commits
b39c237989
...
v2.273.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
24845a5a01 | ||
|
|
a153170771 | ||
|
|
c5904d5da8 | ||
|
|
99b28c4143 | ||
|
|
b75246e0fe | ||
|
|
a41a9ba8c7 | ||
|
|
c18643e529 | ||
|
|
476640fd51 | ||
|
|
d05b9111c6 | ||
|
|
1d68b0448c |
@@ -1,27 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Actions Runner Devcontainer",
|
|
||||||
"image": "mcr.microsoft.com/devcontainers/base:focal",
|
|
||||||
"features": {
|
|
||||||
"ghcr.io/devcontainers/features/docker-in-docker:1": {},
|
|
||||||
"ghcr.io/devcontainers/features/dotnet": {
|
|
||||||
"version": "8.0.416"
|
|
||||||
},
|
|
||||||
"ghcr.io/devcontainers/features/node:1": {
|
|
||||||
"version": "20"
|
|
||||||
},
|
|
||||||
"ghcr.io/devcontainers/features/sshd:1": {
|
|
||||||
"version": "latest"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"customizations": {
|
|
||||||
"vscode": {
|
|
||||||
"extensions": [
|
|
||||||
"ms-azuretools.vscode-docker",
|
|
||||||
"ms-dotnettools.csharp",
|
|
||||||
"eamodio.gitlens"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"postCreateCommand": "dotnet restore src/Test && dotnet restore src/Runner.PluginHost",
|
|
||||||
"remoteUser": "vscode"
|
|
||||||
}
|
|
||||||
6
.gitattributes
vendored
6
.gitattributes
vendored
@@ -20,7 +20,7 @@
|
|||||||
#
|
#
|
||||||
# Merging from the command prompt will add diff markers to the files if there
|
# Merging from the command prompt will add diff markers to the files if there
|
||||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||||
# the diff markers are never inserted). Diff markers may cause the following
|
# the diff markers are never inserted). Diff markers may cause the following
|
||||||
# file extensions to fail to load in VS. An alternative would be to treat
|
# file extensions to fail to load in VS. An alternative would be to treat
|
||||||
# these files as binary and thus will always conflict and require user
|
# these files as binary and thus will always conflict and require user
|
||||||
# intervention with every merge. To do so, just uncomment the entries below
|
# intervention with every merge. To do so, just uncomment the entries below
|
||||||
@@ -70,9 +70,9 @@
|
|||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# diff behavior for common document formats
|
# diff behavior for common document formats
|
||||||
#
|
#
|
||||||
# Convert binary document formats to text before diffing them. This feature
|
# Convert binary document formats to text before diffing them. This feature
|
||||||
# is only available from the command line. Turn it on by uncommenting the
|
# is only available from the command line. Turn it on by uncommenting the
|
||||||
# entries below.
|
# entries below.
|
||||||
###############################################################################
|
###############################################################################
|
||||||
*.doc diff=astextplain
|
*.doc diff=astextplain
|
||||||
|
|||||||
10
.github/ISSUE_TEMPLATE/bug_report.md
vendored
10
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,18 +1,12 @@
|
|||||||
---
|
---
|
||||||
name: 🛑 Report a bug in the runner application
|
name: Bug report
|
||||||
about: If you have issues with GitHub Actions, please follow the "support for GitHub Actions" link, below.
|
about: Create a report to help us improve
|
||||||
title: ''
|
title: ''
|
||||||
labels: bug
|
labels: bug
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<!--
|
|
||||||
👋 You're opening a bug report against the GitHub Actions **runner application**.
|
|
||||||
|
|
||||||
🛑 Please stop if you're not certain that the bug you're seeing is in the runner application - if you have general problems with actions, workflows, or runners, please see the [GitHub Community Support Forum](https://github.community/c/code-to-cloud/52) which is actively monitored. Using the forum ensures that we route your problem to the correct team. 😃
|
|
||||||
-->
|
|
||||||
|
|
||||||
**Describe the bug**
|
**Describe the bug**
|
||||||
A clear and concise description of what the bug is.
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
|||||||
14
.github/ISSUE_TEMPLATE/config.yml
vendored
14
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,14 +0,0 @@
|
|||||||
blank_issues_enabled: false
|
|
||||||
contact_links:
|
|
||||||
- name: 🛑 Request a feature in the runner application
|
|
||||||
url: https://github.com/orgs/community/discussions/categories/actions
|
|
||||||
about: If you have feature requests for GitHub Actions, please use the Actions section on the Github Product Feedback page.
|
|
||||||
- name: ✅ Support for GitHub Actions
|
|
||||||
url: https://github.community/c/code-to-cloud/52
|
|
||||||
about: If you have questions about GitHub Actions or need support writing workflows, please ask in the GitHub Community Support forum.
|
|
||||||
- name: ✅ Feedback and suggestions for GitHub Actions
|
|
||||||
url: https://github.com/github/feedback/discussions/categories/actions
|
|
||||||
about: If you have feedback or suggestions about GitHub Actions, please open a discussion (or add to an existing one) in the GitHub Actions Feedback. GitHub Actions Product Managers and Engineers monitor the feedback forum.
|
|
||||||
- name: ‼️ GitHub Security Bug Bounty
|
|
||||||
url: https://bounty.github.com/
|
|
||||||
about: Please report security vulnerabilities here.
|
|
||||||
27
.github/ISSUE_TEMPLATE/enhancement_request.md
vendored
Normal file
27
.github/ISSUE_TEMPLATE/enhancement_request.md
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
name: Feature Request
|
||||||
|
about: Create a request to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: enhancement
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Thank you 🙇♀ for wanting to create a feature in this repository. Before you do, please ensure you are filing the issue in the right place. Issues should only be opened on if the issue **relates to code in this repository**.
|
||||||
|
|
||||||
|
* If you have found a security issue [please submit it here](https://hackerone.com/github)
|
||||||
|
* If you have questions or issues with the service, writing workflows or actions, then please [visit the GitHub Community Forum's Actions Board](https://github.community/t5/GitHub-Actions/bd-p/actions)
|
||||||
|
* If you are having an issue or question about GitHub Actions then please [contact customer support](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/about-github-actions#contacting-support)
|
||||||
|
|
||||||
|
If you have a feature request that is relevant to this repository, the runner, then please include the information below:
|
||||||
|
|
||||||
|
**Describe the enhancement**
|
||||||
|
A clear and concise description of what the features or enhancement you need.
|
||||||
|
|
||||||
|
**Code Snippet**
|
||||||
|
If applicable, add a code snippet.
|
||||||
|
|
||||||
|
**Additional information**
|
||||||
|
Add any other context about the feature here.
|
||||||
|
|
||||||
|
NOTE: if the feature request has been agreed upon then the assignee will create an ADR. See docs/adrs/README.md
|
||||||
25
.github/copilot-instructions.md
vendored
25
.github/copilot-instructions.md
vendored
@@ -1,25 +0,0 @@
|
|||||||
## Making changes
|
|
||||||
|
|
||||||
### Tests
|
|
||||||
|
|
||||||
Whenever possible, changes should be accompanied by non-trivial tests that meaningfully exercise the core functionality of the new code being introduced.
|
|
||||||
|
|
||||||
All tests are in the `Test/` directory at the repo root. Fast unit tests are in the `Test/L0` directory and by convention have the suffix `L0.cs`. For example: unit tests for a hypothetical `src/Runner.Worker/Foo.cs` would go in `src/Test/L0/Worker/FooL0.cs`.
|
|
||||||
|
|
||||||
Run tests using this command:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cd src && ./dev.sh test
|
|
||||||
```
|
|
||||||
|
|
||||||
### Formatting
|
|
||||||
|
|
||||||
After editing .cs files, always format the code using this command:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cd src && ./dev.sh format
|
|
||||||
```
|
|
||||||
|
|
||||||
### Feature Flags
|
|
||||||
|
|
||||||
Wherever possible, all changes should be safeguarded by a feature flag; `Features` are declared in [Constants.cs](src/Runner.Common/Constants.cs).
|
|
||||||
25
.github/dependabot.yml
vendored
25
.github/dependabot.yml
vendored
@@ -1,25 +0,0 @@
|
|||||||
version: 2
|
|
||||||
updates:
|
|
||||||
- package-ecosystem: "docker"
|
|
||||||
directory: "/images"
|
|
||||||
schedule:
|
|
||||||
interval: "daily"
|
|
||||||
target-branch: "main"
|
|
||||||
- package-ecosystem: "github-actions"
|
|
||||||
directory: "/"
|
|
||||||
schedule:
|
|
||||||
interval: "daily"
|
|
||||||
target-branch: "main"
|
|
||||||
- package-ecosystem: "nuget"
|
|
||||||
directory: "/src"
|
|
||||||
schedule:
|
|
||||||
interval: "daily"
|
|
||||||
target-branch: "main"
|
|
||||||
- package-ecosystem: "npm"
|
|
||||||
directory: "/src/Misc/expressionFunc/hashFiles"
|
|
||||||
schedule:
|
|
||||||
interval: "daily"
|
|
||||||
target-branch: "main"
|
|
||||||
allow:
|
|
||||||
- dependency-type: direct
|
|
||||||
- dependency-type: production # check only dependencies, which are going to the compiled app, not supporting tools like @vue-cli
|
|
||||||
27
.github/workflows/build.yml
vendored
27
.github/workflows/build.yml
vendored
@@ -7,18 +7,18 @@ on:
|
|||||||
- main
|
- main
|
||||||
- releases/*
|
- releases/*
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- '**.md'
|
- '**.md'
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- '**'
|
- '*'
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- '**.md'
|
- '**.md'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, win-arm64, osx-x64, osx-arm64 ]
|
runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, osx-x64 ]
|
||||||
include:
|
include:
|
||||||
- runtime: linux-x64
|
- runtime: linux-x64
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
@@ -36,21 +36,13 @@ jobs:
|
|||||||
os: macOS-latest
|
os: macOS-latest
|
||||||
devScript: ./dev.sh
|
devScript: ./dev.sh
|
||||||
|
|
||||||
- runtime: osx-arm64
|
|
||||||
os: macOS-latest
|
|
||||||
devScript: ./dev.sh
|
|
||||||
|
|
||||||
- runtime: win-x64
|
- runtime: win-x64
|
||||||
os: windows-latest
|
os: windows-latest
|
||||||
devScript: ./dev
|
devScript: ./dev
|
||||||
|
|
||||||
- runtime: win-arm64
|
|
||||||
os: windows-latest
|
|
||||||
devScript: ./dev
|
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v1
|
||||||
|
|
||||||
# Build runner layout
|
# Build runner layout
|
||||||
- name: Build & Layout Release
|
- name: Build & Layout Release
|
||||||
@@ -63,20 +55,19 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
${{ matrix.devScript }} test
|
${{ matrix.devScript }} test
|
||||||
working-directory: src
|
working-directory: src
|
||||||
if: matrix.runtime != 'linux-arm64' && matrix.runtime != 'linux-arm' && matrix.runtime != 'osx-arm64' && matrix.runtime != 'win-arm64'
|
if: matrix.runtime != 'linux-arm64' && matrix.runtime != 'linux-arm'
|
||||||
|
|
||||||
# Create runner package tar.gz/zip
|
# Create runner package tar.gz/zip
|
||||||
- name: Package Release
|
- name: Package Release
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request'
|
||||||
run: |
|
run: |
|
||||||
${{ matrix.devScript }} package Release ${{ matrix.runtime }}
|
${{ matrix.devScript }} package Release
|
||||||
working-directory: src
|
working-directory: src
|
||||||
|
|
||||||
# Upload runner package tar.gz/zip as artifact
|
# Upload runner package tar.gz/zip as artifact
|
||||||
- name: Publish Artifact
|
- name: Publish Artifact
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request'
|
||||||
uses: actions/upload-artifact@v5
|
uses: actions/upload-artifact@v1
|
||||||
with:
|
with:
|
||||||
name: runner-package-${{ matrix.runtime }}
|
name: runner-package-${{ matrix.runtime }}
|
||||||
path: |
|
path: _package
|
||||||
_package
|
|
||||||
|
|||||||
17
.github/workflows/close-bugs-bot.yml
vendored
17
.github/workflows/close-bugs-bot.yml
vendored
@@ -1,17 +0,0 @@
|
|||||||
name: Close Bugs Bot
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0 * * *' # every day at midnight
|
|
||||||
jobs:
|
|
||||||
stale:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/stale@v10
|
|
||||||
with:
|
|
||||||
close-issue-message: "This issue does not seem to be a problem with the runner application, it concerns the GitHub actions platform more generally. Could you please post your feedback on the [GitHub Community Support Forum](https://github.com/orgs/community/discussions/categories/actions) which is actively monitored. Using the forum ensures that we route your problem to the correct team. 😃"
|
|
||||||
exempt-issue-labels: "keep"
|
|
||||||
stale-issue-label: "actions-bug"
|
|
||||||
only-labels: "actions-bug"
|
|
||||||
days-before-stale: 0
|
|
||||||
days-before-close: 1
|
|
||||||
17
.github/workflows/close-features-bot.yml
vendored
17
.github/workflows/close-features-bot.yml
vendored
@@ -1,17 +0,0 @@
|
|||||||
name: Close Features Bot
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0 * * *' # every day at midnight
|
|
||||||
jobs:
|
|
||||||
stale:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/stale@v10
|
|
||||||
with:
|
|
||||||
close-issue-message: "Thank you for your interest in the runner application and taking the time to provide your valuable feedback. We kindly ask you to redirect this feedback to the [GitHub Community Support Forum](https://github.com/orgs/community/discussions/categories/actions) which our team actively monitors and would be a better place to start a discussion for new feature requests in GitHub Actions. For more information on this policy please [read our contribution guidelines](https://github.com/actions/runner#contribute). 😃"
|
|
||||||
exempt-issue-labels: "keep"
|
|
||||||
stale-issue-label: "actions-feature"
|
|
||||||
only-labels: "actions-feature"
|
|
||||||
days-before-stale: 0
|
|
||||||
days-before-close: 1
|
|
||||||
14
.github/workflows/codeql.yml
vendored
14
.github/workflows/codeql.yml
vendored
@@ -1,13 +1,7 @@
|
|||||||
name: "Code Scanning - Action"
|
name: "Code Scanning - Action"
|
||||||
|
|
||||||
permissions:
|
|
||||||
security-events: write
|
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
pull_request:
|
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 0 * * 0'
|
- cron: '0 0 * * 0'
|
||||||
|
|
||||||
@@ -23,19 +17,19 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v4
|
uses: github/codeql-action/init@v1
|
||||||
# Override language selection by uncommenting this and choosing your languages
|
# Override language selection by uncommenting this and choosing your languages
|
||||||
# with:
|
# with:
|
||||||
# languages: go, javascript, csharp, python, cpp, java
|
# languages: go, javascript, csharp, python, cpp, java
|
||||||
|
|
||||||
- name: Manual build
|
- name: Manual build
|
||||||
run : |
|
run : |
|
||||||
./dev.sh layout Release linux-x64
|
./dev.sh layout Release linux-x64
|
||||||
working-directory: src
|
working-directory: src
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v4
|
uses: github/codeql-action/analyze@v1
|
||||||
|
|||||||
211
.github/workflows/dependency-check.yml
vendored
211
.github/workflows/dependency-check.yml
vendored
@@ -1,211 +0,0 @@
|
|||||||
name: Dependency Status Check
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
check_type:
|
|
||||||
description: "Type of dependency check"
|
|
||||||
required: false
|
|
||||||
default: "all"
|
|
||||||
type: choice
|
|
||||||
options:
|
|
||||||
- all
|
|
||||||
- node
|
|
||||||
- dotnet
|
|
||||||
- docker
|
|
||||||
- npm
|
|
||||||
schedule:
|
|
||||||
- cron: "0 11 * * 1" # Weekly on Monday at 11 AM
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
dependency-status:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
node20-status: ${{ steps.check-versions.outputs.node20-status }}
|
|
||||||
node24-status: ${{ steps.check-versions.outputs.node24-status }}
|
|
||||||
dotnet-status: ${{ steps.check-versions.outputs.dotnet-status }}
|
|
||||||
docker-status: ${{ steps.check-versions.outputs.docker-status }}
|
|
||||||
buildx-status: ${{ steps.check-versions.outputs.buildx-status }}
|
|
||||||
npm-vulnerabilities: ${{ steps.check-versions.outputs.npm-vulnerabilities }}
|
|
||||||
open-dependency-prs: ${{ steps.check-prs.outputs.open-dependency-prs }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@v6
|
|
||||||
with:
|
|
||||||
node-version: "20"
|
|
||||||
|
|
||||||
- name: Check dependency versions
|
|
||||||
id: check-versions
|
|
||||||
run: |
|
|
||||||
echo "## Dependency Status Report" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "Generated on: $(date)" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
|
||||||
|
|
||||||
# Check Node versions
|
|
||||||
if [[ "${{ github.event.inputs.check_type }}" == "all" || "${{ github.event.inputs.check_type }}" == "node" ]]; then
|
|
||||||
echo "### Node.js Versions" >> $GITHUB_STEP_SUMMARY
|
|
||||||
|
|
||||||
VERSIONS_JSON=$(curl -s https://raw.githubusercontent.com/actions/node-versions/main/versions-manifest.json)
|
|
||||||
LATEST_NODE20=$(echo "$VERSIONS_JSON" | jq -r '.[] | select(.version | startswith("20.")) | .version' | head -1)
|
|
||||||
LATEST_NODE24=$(echo "$VERSIONS_JSON" | jq -r '.[] | select(.version | startswith("24.")) | .version' | head -1)
|
|
||||||
|
|
||||||
CURRENT_NODE20=$(grep "NODE20_VERSION=" src/Misc/externals.sh | cut -d'"' -f2)
|
|
||||||
CURRENT_NODE24=$(grep "NODE24_VERSION=" src/Misc/externals.sh | cut -d'"' -f2)
|
|
||||||
|
|
||||||
NODE20_STATUS="✅ up-to-date"
|
|
||||||
NODE24_STATUS="✅ up-to-date"
|
|
||||||
|
|
||||||
if [ "$CURRENT_NODE20" != "$LATEST_NODE20" ]; then
|
|
||||||
NODE20_STATUS="⚠️ outdated"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$CURRENT_NODE24" != "$LATEST_NODE24" ]; then
|
|
||||||
NODE24_STATUS="⚠️ outdated"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "| Version | Current | Latest | Status |" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "|---------|---------|--------|--------|" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "| Node 20 | $CURRENT_NODE20 | $LATEST_NODE20 | $NODE20_STATUS |" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "| Node 24 | $CURRENT_NODE24 | $LATEST_NODE24 | $NODE24_STATUS |" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
|
||||||
|
|
||||||
echo "node20-status=$NODE20_STATUS" >> $GITHUB_OUTPUT
|
|
||||||
echo "node24-status=$NODE24_STATUS" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check .NET version
|
|
||||||
if [[ "${{ github.event.inputs.check_type }}" == "all" || "${{ github.event.inputs.check_type }}" == "dotnet" ]]; then
|
|
||||||
echo "### .NET SDK Version" >> $GITHUB_STEP_SUMMARY
|
|
||||||
|
|
||||||
current_dotnet_version=$(jq -r .sdk.version ./src/global.json)
|
|
||||||
current_major_minor=$(echo "$current_dotnet_version" | cut -d '.' -f 1,2)
|
|
||||||
latest_dotnet_version=$(curl -sb -H "Accept: application/json" "https://dotnetcli.blob.core.windows.net/dotnet/Sdk/$current_major_minor/latest.version")
|
|
||||||
|
|
||||||
DOTNET_STATUS="✅ up-to-date"
|
|
||||||
if [ "$current_dotnet_version" != "$latest_dotnet_version" ]; then
|
|
||||||
DOTNET_STATUS="⚠️ outdated"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "| Component | Current | Latest | Status |" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "|-----------|---------|--------|--------|" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "| .NET SDK | $current_dotnet_version | $latest_dotnet_version | $DOTNET_STATUS |" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
|
||||||
|
|
||||||
echo "dotnet-status=$DOTNET_STATUS" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check Docker versions
|
|
||||||
if [[ "${{ github.event.inputs.check_type }}" == "all" || "${{ github.event.inputs.check_type }}" == "docker" ]]; then
|
|
||||||
echo "### Docker Versions" >> $GITHUB_STEP_SUMMARY
|
|
||||||
|
|
||||||
current_docker=$(grep "ARG DOCKER_VERSION=" ./images/Dockerfile | cut -d'=' -f2)
|
|
||||||
current_buildx=$(grep "ARG BUILDX_VERSION=" ./images/Dockerfile | cut -d'=' -f2)
|
|
||||||
|
|
||||||
latest_docker=$(curl -s https://download.docker.com/linux/static/stable/x86_64/ | grep -o 'docker-[0-9]*\.[0-9]*\.[0-9]*\.tgz' | sort -V | tail -n 1 | sed 's/docker-\(.*\)\.tgz/\1/')
|
|
||||||
latest_buildx=$(curl -s https://api.github.com/repos/docker/buildx/releases/latest | jq -r '.tag_name' | sed 's/^v//')
|
|
||||||
|
|
||||||
DOCKER_STATUS="✅ up-to-date"
|
|
||||||
BUILDX_STATUS="✅ up-to-date"
|
|
||||||
|
|
||||||
if [ "$current_docker" != "$latest_docker" ]; then
|
|
||||||
DOCKER_STATUS="⚠️ outdated"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$current_buildx" != "$latest_buildx" ]; then
|
|
||||||
BUILDX_STATUS="⚠️ outdated"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "| Component | Current | Latest | Status |" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "|-----------|---------|--------|--------|" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "| Docker | $current_docker | $latest_docker | $DOCKER_STATUS |" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "| Docker Buildx | $current_buildx | $latest_buildx | $BUILDX_STATUS |" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
|
||||||
|
|
||||||
echo "docker-status=$DOCKER_STATUS" >> $GITHUB_OUTPUT
|
|
||||||
echo "buildx-status=$BUILDX_STATUS" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check npm vulnerabilities
|
|
||||||
if [[ "${{ github.event.inputs.check_type }}" == "all" || "${{ github.event.inputs.check_type }}" == "npm" ]]; then
|
|
||||||
echo "### NPM Security Audit" >> $GITHUB_STEP_SUMMARY
|
|
||||||
|
|
||||||
cd src/Misc/expressionFunc/hashFiles
|
|
||||||
npm install --silent
|
|
||||||
|
|
||||||
AUDIT_OUTPUT=""
|
|
||||||
AUDIT_EXIT_CODE=0
|
|
||||||
# Run npm audit and capture output and exit code
|
|
||||||
if ! AUDIT_OUTPUT=$(npm audit --json 2>&1); then
|
|
||||||
AUDIT_EXIT_CODE=$?
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if output is valid JSON
|
|
||||||
if echo "$AUDIT_OUTPUT" | jq . >/dev/null 2>&1; then
|
|
||||||
VULN_COUNT=$(echo "$AUDIT_OUTPUT" | jq '.metadata.vulnerabilities.total // 0')
|
|
||||||
# Ensure VULN_COUNT is a number
|
|
||||||
VULN_COUNT=$(echo "$VULN_COUNT" | grep -o '[0-9]*' | head -1)
|
|
||||||
VULN_COUNT=${VULN_COUNT:-0}
|
|
||||||
|
|
||||||
NPM_STATUS="✅ no vulnerabilities"
|
|
||||||
if [ "$VULN_COUNT" -gt 0 ] 2>/dev/null; then
|
|
||||||
NPM_STATUS="⚠️ $VULN_COUNT vulnerabilities found"
|
|
||||||
|
|
||||||
# Get vulnerability details
|
|
||||||
HIGH_VULNS=$(echo "$AUDIT_OUTPUT" | jq '.metadata.vulnerabilities.high // 0')
|
|
||||||
CRITICAL_VULNS=$(echo "$AUDIT_OUTPUT" | jq '.metadata.vulnerabilities.critical // 0')
|
|
||||||
|
|
||||||
echo "| Severity | Count |" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "| Critical | $CRITICAL_VULNS |" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "| High | $HIGH_VULNS |" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
|
||||||
else
|
|
||||||
echo "No npm vulnerabilities found ✅" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
NPM_STATUS="❌ npm audit failed"
|
|
||||||
echo "npm audit failed to run or returned invalid JSON ❌" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "Exit code: $AUDIT_EXIT_CODE" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "Output: $AUDIT_OUTPUT" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "npm-vulnerabilities=$NPM_STATUS" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Check for open dependency PRs
|
|
||||||
id: check-prs
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
echo "### Open Dependency PRs" >> $GITHUB_STEP_SUMMARY
|
|
||||||
|
|
||||||
# Get open PRs with dependency label
|
|
||||||
OPEN_PRS=$(gh pr list --label "dependencies" --state open --json number,title,url)
|
|
||||||
PR_COUNT=$(echo "$OPEN_PRS" | jq '. | length')
|
|
||||||
|
|
||||||
if [ "$PR_COUNT" -gt 0 ]; then
|
|
||||||
echo "Found $PR_COUNT open dependency PR(s):" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "$OPEN_PRS" | jq -r '.[] | "- [#\(.number)](\(.url)) \(.title)"' >> $GITHUB_STEP_SUMMARY
|
|
||||||
else
|
|
||||||
echo "No open dependency PRs found ✅" >> $GITHUB_STEP_SUMMARY
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "open-dependency-prs=$PR_COUNT" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Summary
|
|
||||||
run: |
|
|
||||||
echo "### Summary" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "- Check for open PRs with the \`dependency\` label before releases" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "- Review and merge dependency updates regularly" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "- Critical vulnerabilities should be addressed immediately" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "**Automated workflows run weekly to check for updates:**" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "- Node.js versions (Mondays at 6 AM)" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "- NPM audit fix (Mondays at 7 AM)" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "- .NET SDK updates (Mondays at midnight)" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "- Docker/Buildx updates (Mondays at midnight)" >> $GITHUB_STEP_SUMMARY
|
|
||||||
166
.github/workflows/docker-buildx-upgrade.yml
vendored
166
.github/workflows/docker-buildx-upgrade.yml
vendored
@@ -1,166 +0,0 @@
|
|||||||
name: "Docker/Buildx Version Upgrade"
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: "0 0 * * 1" # Run every Monday at midnight
|
|
||||||
workflow_dispatch: # Allow manual triggering
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
check-versions:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
DOCKER_SHOULD_UPDATE: ${{ steps.check_docker_version.outputs.SHOULD_UPDATE }}
|
|
||||||
DOCKER_LATEST_VERSION: ${{ steps.check_docker_version.outputs.LATEST_VERSION }}
|
|
||||||
DOCKER_CURRENT_VERSION: ${{ steps.check_docker_version.outputs.CURRENT_VERSION }}
|
|
||||||
BUILDX_SHOULD_UPDATE: ${{ steps.check_buildx_version.outputs.SHOULD_UPDATE }}
|
|
||||||
BUILDX_LATEST_VERSION: ${{ steps.check_buildx_version.outputs.LATEST_VERSION }}
|
|
||||||
BUILDX_CURRENT_VERSION: ${{ steps.check_buildx_version.outputs.CURRENT_VERSION }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
|
|
||||||
- name: Check Docker version
|
|
||||||
id: check_docker_version
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
# Extract current Docker version from Dockerfile
|
|
||||||
current_version=$(grep "ARG DOCKER_VERSION=" ./images/Dockerfile | cut -d'=' -f2)
|
|
||||||
|
|
||||||
# Fetch latest Docker Engine version from Docker's download site
|
|
||||||
# This gets the latest Linux static binary version which matches what's used in the Dockerfile
|
|
||||||
latest_version=$(curl -s https://download.docker.com/linux/static/stable/x86_64/ | grep -o 'docker-[0-9]*\.[0-9]*\.[0-9]*\.tgz' | sort -V | tail -n 1 | sed 's/docker-\(.*\)\.tgz/\1/')
|
|
||||||
|
|
||||||
# Extra check to ensure we got a valid version
|
|
||||||
if [[ ! $latest_version =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
||||||
echo "Failed to retrieve a valid Docker version"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
should_update=0
|
|
||||||
[ "$current_version" != "$latest_version" ] && should_update=1
|
|
||||||
|
|
||||||
echo "CURRENT_VERSION=${current_version}" >> $GITHUB_OUTPUT
|
|
||||||
echo "LATEST_VERSION=${latest_version}" >> $GITHUB_OUTPUT
|
|
||||||
echo "SHOULD_UPDATE=${should_update}" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Check Buildx version
|
|
||||||
id: check_buildx_version
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
# Extract current Buildx version from Dockerfile
|
|
||||||
current_version=$(grep "ARG BUILDX_VERSION=" ./images/Dockerfile | cut -d'=' -f2)
|
|
||||||
|
|
||||||
# Fetch latest Buildx version
|
|
||||||
latest_version=$(curl -s https://api.github.com/repos/docker/buildx/releases/latest | jq -r '.tag_name' | sed 's/^v//')
|
|
||||||
|
|
||||||
should_update=0
|
|
||||||
[ "$current_version" != "$latest_version" ] && should_update=1
|
|
||||||
|
|
||||||
echo "CURRENT_VERSION=${current_version}" >> $GITHUB_OUTPUT
|
|
||||||
echo "LATEST_VERSION=${latest_version}" >> $GITHUB_OUTPUT
|
|
||||||
echo "SHOULD_UPDATE=${should_update}" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Create annotations for versions
|
|
||||||
run: |
|
|
||||||
docker_should_update="${{ steps.check_docker_version.outputs.SHOULD_UPDATE }}"
|
|
||||||
buildx_should_update="${{ steps.check_buildx_version.outputs.SHOULD_UPDATE }}"
|
|
||||||
|
|
||||||
# Show annotation if only Docker needs update
|
|
||||||
if [[ "$docker_should_update" == "1" && "$buildx_should_update" == "0" ]]; then
|
|
||||||
echo "::warning ::Docker version (${{ steps.check_docker_version.outputs.LATEST_VERSION }}) needs update but Buildx is current. Only updating when both need updates."
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Show annotation if only Buildx needs update
|
|
||||||
if [[ "$docker_should_update" == "0" && "$buildx_should_update" == "1" ]]; then
|
|
||||||
echo "::warning ::Buildx version (${{ steps.check_buildx_version.outputs.LATEST_VERSION }}) needs update but Docker is current. Only updating when both need updates."
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Show annotation when both are current
|
|
||||||
if [[ "$docker_should_update" == "0" && "$buildx_should_update" == "0" ]]; then
|
|
||||||
echo "::warning ::Latest Docker version is ${{ steps.check_docker_version.outputs.LATEST_VERSION }} and Buildx version is ${{ steps.check_buildx_version.outputs.LATEST_VERSION }}. No updates needed."
|
|
||||||
fi
|
|
||||||
|
|
||||||
update-versions:
|
|
||||||
permissions:
|
|
||||||
pull-requests: write
|
|
||||||
contents: write
|
|
||||||
needs: [check-versions]
|
|
||||||
if: ${{ needs.check-versions.outputs.DOCKER_SHOULD_UPDATE == 1 && needs.check-versions.outputs.BUILDX_SHOULD_UPDATE == 1 }}
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
|
|
||||||
- name: Update Docker version
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
latest_version="${{ needs.check-versions.outputs.DOCKER_LATEST_VERSION }}"
|
|
||||||
current_version="${{ needs.check-versions.outputs.DOCKER_CURRENT_VERSION }}"
|
|
||||||
|
|
||||||
# Update version in Dockerfile
|
|
||||||
sed -i "s/ARG DOCKER_VERSION=$current_version/ARG DOCKER_VERSION=$latest_version/g" ./images/Dockerfile
|
|
||||||
|
|
||||||
- name: Update Buildx version
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
latest_version="${{ needs.check-versions.outputs.BUILDX_LATEST_VERSION }}"
|
|
||||||
current_version="${{ needs.check-versions.outputs.BUILDX_CURRENT_VERSION }}"
|
|
||||||
|
|
||||||
# Update version in Dockerfile
|
|
||||||
sed -i "s/ARG BUILDX_VERSION=$current_version/ARG BUILDX_VERSION=$latest_version/g" ./images/Dockerfile
|
|
||||||
|
|
||||||
- name: Commit changes and create Pull Request
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
# Setup branch and commit information
|
|
||||||
branch_name="feature/docker-buildx-upgrade"
|
|
||||||
commit_message="Upgrade Docker to v${{ needs.check-versions.outputs.DOCKER_LATEST_VERSION }} and Buildx to v${{ needs.check-versions.outputs.BUILDX_LATEST_VERSION }}"
|
|
||||||
pr_title="Update Docker to v${{ needs.check-versions.outputs.DOCKER_LATEST_VERSION }} and Buildx to v${{ needs.check-versions.outputs.BUILDX_LATEST_VERSION }}"
|
|
||||||
|
|
||||||
# Configure git
|
|
||||||
git config --global user.name "github-actions[bot]"
|
|
||||||
git config --global user.email "<41898282+github-actions[bot]@users.noreply.github.com>"
|
|
||||||
|
|
||||||
# Create branch or switch to it if it exists
|
|
||||||
if git show-ref --quiet refs/remotes/origin/$branch_name; then
|
|
||||||
git fetch origin
|
|
||||||
git checkout -B "$branch_name" origin/$branch_name
|
|
||||||
else
|
|
||||||
git checkout -b "$branch_name"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Commit and push changes
|
|
||||||
git commit -a -m "$commit_message"
|
|
||||||
git push --force origin "$branch_name"
|
|
||||||
|
|
||||||
# Create PR body using here-doc for proper formatting
|
|
||||||
cat > pr_body.txt << 'EOF'
|
|
||||||
Automated Docker and Buildx version update:
|
|
||||||
|
|
||||||
- Docker: ${{ needs.check-versions.outputs.DOCKER_CURRENT_VERSION }} → ${{ needs.check-versions.outputs.DOCKER_LATEST_VERSION }}
|
|
||||||
- Buildx: ${{ needs.check-versions.outputs.BUILDX_CURRENT_VERSION }} → ${{ needs.check-versions.outputs.BUILDX_LATEST_VERSION }}
|
|
||||||
|
|
||||||
This update ensures we're using the latest stable Docker and Buildx versions for security and performance improvements.
|
|
||||||
|
|
||||||
**Release notes:** https://docs.docker.com/engine/release-notes/
|
|
||||||
|
|
||||||
**Next steps:**
|
|
||||||
- Review the version changes
|
|
||||||
- Verify container builds work as expected
|
|
||||||
- Test multi-platform builds if applicable
|
|
||||||
- Merge when ready
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Autogenerated by [Docker/Buildx Version Upgrade Workflow](https://github.com/actions/runner/blob/main/.github/workflows/docker-buildx-upgrade.yml)
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Create PR
|
|
||||||
gh pr create -B main -H "$branch_name" \
|
|
||||||
--title "$pr_title" \
|
|
||||||
--label "dependencies" \
|
|
||||||
--label "dependencies-weekly-check" \
|
|
||||||
--label "dependencies-not-dependabot" \
|
|
||||||
--label "docker" \
|
|
||||||
--body-file pr_body.txt
|
|
||||||
105
.github/workflows/dotnet-upgrade.yml
vendored
105
.github/workflows/dotnet-upgrade.yml
vendored
@@ -1,105 +0,0 @@
|
|||||||
name: "DotNet SDK Upgrade"
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: "0 8 * * 1" # Weekly on Monday at 8 AM UTC (independent of Node.js/NPM)
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
dotnet-update:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
SHOULD_UPDATE: ${{ steps.fetch_latest_version.outputs.SHOULD_UPDATE }}
|
|
||||||
BRANCH_EXISTS: ${{ steps.fetch_latest_version.outputs.BRANCH_EXISTS }}
|
|
||||||
DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION: ${{ steps.fetch_latest_version.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}
|
|
||||||
DOTNET_CURRENT_MAJOR_MINOR_VERSION: ${{ steps.fetch_current_version.outputs.DOTNET_CURRENT_MAJOR_MINOR_VERSION }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
- name: Get current major minor version
|
|
||||||
id: fetch_current_version
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
current_major_minor_patch_version=$(jq .sdk.version ./src/global.json | xargs)
|
|
||||||
current_major_minor_version=$(cut -d '.' -f 1,2 <<< "$current_major_minor_patch_version")
|
|
||||||
|
|
||||||
echo "DOTNET_CURRENT_MAJOR_MINOR_PATCH_VERSION=${current_major_minor_patch_version}" >> $GITHUB_OUTPUT
|
|
||||||
echo "DOTNET_CURRENT_MAJOR_MINOR_VERSION=${current_major_minor_version}" >> $GITHUB_OUTPUT
|
|
||||||
- name: Check patch version
|
|
||||||
id: fetch_latest_version
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
latest_patch_version=$(curl -sb -H "Accept: application/json" "https://dotnetcli.blob.core.windows.net/dotnet/Sdk/${{ steps.fetch_current_version.outputs.DOTNET_CURRENT_MAJOR_MINOR_VERSION }}/latest.version")
|
|
||||||
current_patch_version=${{ steps.fetch_current_version.outputs.DOTNET_CURRENT_MAJOR_MINOR_PATCH_VERSION }}
|
|
||||||
|
|
||||||
should_update=0
|
|
||||||
[ "$current_patch_version" != "$latest_patch_version" ] && should_update=1
|
|
||||||
|
|
||||||
# check if git branch already exists for the upgrade
|
|
||||||
branch_already_exists=0
|
|
||||||
|
|
||||||
if git ls-remote --heads --exit-code origin refs/heads/feature/dotnetsdk-upgrade/${latest_patch_version};
|
|
||||||
then
|
|
||||||
branch_already_exists=1
|
|
||||||
should_update=0
|
|
||||||
fi
|
|
||||||
echo "DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION=${latest_patch_version}" >> $GITHUB_OUTPUT
|
|
||||||
echo "SHOULD_UPDATE=${should_update}" >> $GITHUB_OUTPUT
|
|
||||||
echo "BRANCH_EXISTS=${branch_already_exists}" >> $GITHUB_OUTPUT
|
|
||||||
- name: Create an error annotation if branch exists
|
|
||||||
if: ${{ steps.fetch_latest_version.outputs.BRANCH_EXISTS == 1 }}
|
|
||||||
run: echo "::error links::feature/dotnet-sdk-upgrade${{ steps.fetch_latest_version.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }} https://github.com/actions/runner/tree/feature/dotnet-sdk-upgrade${{ steps.fetch_latest_version.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}::Branch feature/dotnetsdk-upgrade/${{ steps.fetch_latest_version.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }} already exists. Please take a look and delete that branch if you wish to recreate"
|
|
||||||
- name: Create a warning annotation if no need to update
|
|
||||||
if: ${{ steps.fetch_latest_version.outputs.SHOULD_UPDATE == 0 && steps.fetch_latest_version.outputs.BRANCH_EXISTS == 0 }}
|
|
||||||
run: echo "::warning ::Latest DotNet SDK patch is ${{ steps.fetch_latest_version.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}, and we are on ${{ steps.fetch_current_version.outputs.DOTNET_CURRENT_MAJOR_MINOR_PATCH_VERSION }}. No need to update"
|
|
||||||
- name: Update patch version
|
|
||||||
if: ${{ steps.fetch_latest_version.outputs.SHOULD_UPDATE == 1 && steps.fetch_latest_version.outputs.BRANCH_EXISTS == 0 }}
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
patch_version="${{ steps.fetch_latest_version.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}"
|
|
||||||
current_version="${{ steps.fetch_current_version.outputs.DOTNET_CURRENT_MAJOR_MINOR_PATCH_VERSION }}"
|
|
||||||
|
|
||||||
# Update globals
|
|
||||||
echo Updating globals
|
|
||||||
globals_temp=$(mktemp)
|
|
||||||
jq --unbuffered --arg patch_version "$patch_version" '.sdk.version = $patch_version' ./src/global.json > "$globals_temp" && mv "$globals_temp" ./src/global.json
|
|
||||||
|
|
||||||
# Update devcontainer
|
|
||||||
echo Updating devcontainer
|
|
||||||
devcontainer_temp=$(mktemp)
|
|
||||||
jq --unbuffered --arg patch_version "$patch_version" '.features."ghcr.io/devcontainers/features/dotnet".version = $patch_version' ./.devcontainer/devcontainer.json > "$devcontainer_temp" && mv "$devcontainer_temp" ./.devcontainer/devcontainer.json
|
|
||||||
|
|
||||||
# Update dev.sh
|
|
||||||
echo Updating start script
|
|
||||||
sed -i "s/DOTNETSDK_VERSION=\"$current_version\"/DOTNETSDK_VERSION=\"$patch_version\"/g" ./src/dev.sh
|
|
||||||
- name: GIT commit and push all changed files
|
|
||||||
if: ${{ steps.fetch_latest_version.outputs.SHOULD_UPDATE == 1 && steps.fetch_latest_version.outputs.BRANCH_EXISTS == 0 }}
|
|
||||||
id: create_branch
|
|
||||||
run: |
|
|
||||||
branch_name="feature/dotnetsdk-upgrade/${{ steps.fetch_latest_version.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}"
|
|
||||||
git config --global user.name "github-actions[bot]"
|
|
||||||
git config --global user.email "<41898282+github-actions[bot]@users.noreply.github.com>"
|
|
||||||
|
|
||||||
git checkout -b $branch_name
|
|
||||||
git commit -a -m "Upgrade dotnet sdk to v${{ steps.fetch_latest_version.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}"
|
|
||||||
git push --set-upstream origin $branch_name
|
|
||||||
|
|
||||||
create-pr:
|
|
||||||
needs: [dotnet-update]
|
|
||||||
if: ${{ needs.dotnet-update.outputs.SHOULD_UPDATE == 1 && needs.dotnet-update.outputs.BRANCH_EXISTS == 0 }}
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
with:
|
|
||||||
ref: feature/dotnetsdk-upgrade/${{ needs.dotnet-update.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}
|
|
||||||
- name: Create Pull Request
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
gh pr create -B main -H feature/dotnetsdk-upgrade/${{ needs.dotnet-update.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }} --title "Update dotnet sdk to latest version @${{ needs.dotnet-update.outputs.DOTNET_LATEST_MAJOR_MINOR_PATCH_VERSION }}" --label "dependencies" --label "dependencies-weekly-check" --label "dependencies-not-dependabot" --label "dotnet" --body "
|
|
||||||
https://dotnetcli.blob.core.windows.net/dotnet/Sdk/${{ needs.dotnet-update.outputs.DOTNET_CURRENT_MAJOR_MINOR_VERSION }}/latest.version
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Autogenerated by [DotNet SDK Upgrade Workflow](https://github.com/actions/runner/blob/main/.github/workflows/dotnet-upgrade.yml)"
|
|
||||||
194
.github/workflows/node-upgrade.yml
vendored
194
.github/workflows/node-upgrade.yml
vendored
@@ -1,194 +0,0 @@
|
|||||||
name: Auto Update Node Version
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: "0 6 * * 1" # Weekly, every Monday
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
update-node:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: Get latest Node versions
|
|
||||||
id: node-versions
|
|
||||||
run: |
|
|
||||||
# Get latest Node.js releases from official GitHub releases
|
|
||||||
echo "Fetching latest Node.js releases..."
|
|
||||||
|
|
||||||
# Get latest v20.x release
|
|
||||||
LATEST_NODE20=$(curl -s https://api.github.com/repos/nodejs/node/releases | \
|
|
||||||
jq -r '.[] | select(.tag_name | startswith("v20.")) | .tag_name' | \
|
|
||||||
head -1 | sed 's/^v//')
|
|
||||||
|
|
||||||
# Get latest v24.x release
|
|
||||||
LATEST_NODE24=$(curl -s https://api.github.com/repos/nodejs/node/releases | \
|
|
||||||
jq -r '.[] | select(.tag_name | startswith("v24.")) | .tag_name' | \
|
|
||||||
head -1 | sed 's/^v//')
|
|
||||||
|
|
||||||
echo "Found Node.js releases: 20=$LATEST_NODE20, 24=$LATEST_NODE24"
|
|
||||||
|
|
||||||
# Verify these versions are available in alpine_nodejs releases
|
|
||||||
echo "Verifying availability in alpine_nodejs..."
|
|
||||||
ALPINE_RELEASES=$(curl -s https://api.github.com/repos/actions/alpine_nodejs/releases | jq -r '.[].tag_name')
|
|
||||||
|
|
||||||
if ! echo "$ALPINE_RELEASES" | grep -q "^v$LATEST_NODE20$"; then
|
|
||||||
echo "::warning title=Node 20 Fallback::Node 20 version $LATEST_NODE20 not found in alpine_nodejs releases, using fallback"
|
|
||||||
# Fall back to latest available alpine_nodejs v20 release
|
|
||||||
LATEST_NODE20=$(echo "$ALPINE_RELEASES" | grep "^v20\." | head -1 | sed 's/^v//')
|
|
||||||
echo "Using latest available alpine_nodejs Node 20: $LATEST_NODE20"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! echo "$ALPINE_RELEASES" | grep -q "^v$LATEST_NODE24$"; then
|
|
||||||
echo "::warning title=Node 24 Fallback::Node 24 version $LATEST_NODE24 not found in alpine_nodejs releases, using fallback"
|
|
||||||
# Fall back to latest available alpine_nodejs v24 release
|
|
||||||
LATEST_NODE24=$(echo "$ALPINE_RELEASES" | grep "^v24\." | head -1 | sed 's/^v//')
|
|
||||||
echo "Using latest available alpine_nodejs Node 24: $LATEST_NODE24"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Validate that we have non-empty version numbers
|
|
||||||
if [ -z "$LATEST_NODE20" ] || [ "$LATEST_NODE20" = "" ]; then
|
|
||||||
echo "::error title=Invalid Node 20 Version::Failed to determine valid Node 20 version. Got: '$LATEST_NODE20'"
|
|
||||||
echo "Available alpine_nodejs releases:"
|
|
||||||
echo "$ALPINE_RELEASES" | head -10
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$LATEST_NODE24" ] || [ "$LATEST_NODE24" = "" ]; then
|
|
||||||
echo "::error title=Invalid Node 24 Version::Failed to determine valid Node 24 version. Got: '$LATEST_NODE24'"
|
|
||||||
echo "Available alpine_nodejs releases:"
|
|
||||||
echo "$ALPINE_RELEASES" | head -10
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Additional validation: ensure versions match expected format (x.y.z)
|
|
||||||
if ! echo "$LATEST_NODE20" | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$'; then
|
|
||||||
echo "::error title=Invalid Node 20 Format::Node 20 version '$LATEST_NODE20' does not match expected format (x.y.z)"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! echo "$LATEST_NODE24" | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$'; then
|
|
||||||
echo "::error title=Invalid Node 24 Format::Node 24 version '$LATEST_NODE24' does not match expected format (x.y.z)"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "✅ Validated Node versions: 20=$LATEST_NODE20, 24=$LATEST_NODE24"
|
|
||||||
echo "latest_node20=$LATEST_NODE20" >> $GITHUB_OUTPUT
|
|
||||||
echo "latest_node24=$LATEST_NODE24" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
# Check current versions in externals.sh
|
|
||||||
CURRENT_NODE20=$(grep "NODE20_VERSION=" src/Misc/externals.sh | cut -d'"' -f2)
|
|
||||||
CURRENT_NODE24=$(grep "NODE24_VERSION=" src/Misc/externals.sh | cut -d'"' -f2)
|
|
||||||
|
|
||||||
echo "current_node20=$CURRENT_NODE20" >> $GITHUB_OUTPUT
|
|
||||||
echo "current_node24=$CURRENT_NODE24" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
# Determine if updates are needed
|
|
||||||
NEEDS_UPDATE20="false"
|
|
||||||
NEEDS_UPDATE24="false"
|
|
||||||
|
|
||||||
if [ "$CURRENT_NODE20" != "$LATEST_NODE20" ]; then
|
|
||||||
NEEDS_UPDATE20="true"
|
|
||||||
echo "::notice title=Node 20 Update Available::Current: $CURRENT_NODE20 → Latest: $LATEST_NODE20"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$CURRENT_NODE24" != "$LATEST_NODE24" ]; then
|
|
||||||
NEEDS_UPDATE24="true"
|
|
||||||
echo "::notice title=Node 24 Update Available::Current: $CURRENT_NODE24 → Latest: $LATEST_NODE24"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$NEEDS_UPDATE20" == "false" ] && [ "$NEEDS_UPDATE24" == "false" ]; then
|
|
||||||
echo "::notice title=No Updates Needed::All Node.js versions are up to date"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "needs_update20=$NEEDS_UPDATE20" >> $GITHUB_OUTPUT
|
|
||||||
echo "needs_update24=$NEEDS_UPDATE24" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Update externals.sh and create PR
|
|
||||||
if: steps.node-versions.outputs.needs_update20 == 'true' || steps.node-versions.outputs.needs_update24 == 'true'
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
# Final validation before making changes
|
|
||||||
NODE20_VERSION="${{ steps.node-versions.outputs.latest_node20 }}"
|
|
||||||
NODE24_VERSION="${{ steps.node-versions.outputs.latest_node24 }}"
|
|
||||||
|
|
||||||
echo "Final validation of versions before PR creation:"
|
|
||||||
echo "Node 20: '$NODE20_VERSION'"
|
|
||||||
echo "Node 24: '$NODE24_VERSION'"
|
|
||||||
|
|
||||||
# Validate versions are not empty and match expected format
|
|
||||||
if [ -z "$NODE20_VERSION" ] || ! echo "$NODE20_VERSION" | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$'; then
|
|
||||||
echo "::error title=Invalid Node 20 Version::Refusing to create PR with invalid Node 20 version: '$NODE20_VERSION'"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$NODE24_VERSION" ] || ! echo "$NODE24_VERSION" | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$'; then
|
|
||||||
echo "::error title=Invalid Node 24 Version::Refusing to create PR with invalid Node 24 version: '$NODE24_VERSION'"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "✅ All versions validated successfully"
|
|
||||||
|
|
||||||
# Update the files
|
|
||||||
if [ "${{ steps.node-versions.outputs.needs_update20 }}" == "true" ]; then
|
|
||||||
sed -i 's/NODE20_VERSION="[^"]*"/NODE20_VERSION="'"$NODE20_VERSION"'"/' src/Misc/externals.sh
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${{ steps.node-versions.outputs.needs_update24 }}" == "true" ]; then
|
|
||||||
sed -i 's/NODE24_VERSION="[^"]*"/NODE24_VERSION="'"$NODE24_VERSION"'"/' src/Misc/externals.sh
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Verify the changes were applied correctly
|
|
||||||
echo "Verifying changes in externals.sh:"
|
|
||||||
grep "NODE20_VERSION=" src/Misc/externals.sh
|
|
||||||
grep "NODE24_VERSION=" src/Misc/externals.sh
|
|
||||||
|
|
||||||
# Ensure we actually have valid versions in the file
|
|
||||||
UPDATED_NODE20=$(grep "NODE20_VERSION=" src/Misc/externals.sh | cut -d'"' -f2)
|
|
||||||
UPDATED_NODE24=$(grep "NODE24_VERSION=" src/Misc/externals.sh | cut -d'"' -f2)
|
|
||||||
|
|
||||||
if [ -z "$UPDATED_NODE20" ] || [ -z "$UPDATED_NODE24" ]; then
|
|
||||||
echo "::error title=Update Failed::Failed to properly update externals.sh"
|
|
||||||
echo "Updated Node 20: '$UPDATED_NODE20'"
|
|
||||||
echo "Updated Node 24: '$UPDATED_NODE24'"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Configure git
|
|
||||||
git config --global user.name "github-actions[bot]"
|
|
||||||
git config --global user.email "<41898282+github-actions[bot]@users.noreply.github.com>"
|
|
||||||
|
|
||||||
# Create branch and commit changes
|
|
||||||
branch_name="chore/update-node"
|
|
||||||
git checkout -b "$branch_name"
|
|
||||||
git commit -a -m "chore: update Node versions (20: $NODE20_VERSION, 24: $NODE24_VERSION)"
|
|
||||||
git push --force origin "$branch_name"
|
|
||||||
|
|
||||||
# Create PR body using here-doc for proper formatting
|
|
||||||
cat > pr_body.txt << EOF
|
|
||||||
Automated Node.js version update:
|
|
||||||
|
|
||||||
- Node 20: ${{ steps.node-versions.outputs.current_node20 }} → $NODE20_VERSION
|
|
||||||
- Node 24: ${{ steps.node-versions.outputs.current_node24 }} → $NODE24_VERSION
|
|
||||||
|
|
||||||
This update ensures we're using the latest stable Node.js versions for security and performance improvements.
|
|
||||||
|
|
||||||
**Note**: When updating Node versions, remember to also create a new release of alpine_nodejs at the updated version following the instructions at: https://github.com/actions/alpine_nodejs
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Autogenerated by [Node Version Upgrade Workflow](https://github.com/actions/runner/blob/main/.github/workflows/node-upgrade.yml)
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Create PR
|
|
||||||
gh pr create -B main -H "$branch_name" \
|
|
||||||
--title "chore: update Node versions" \
|
|
||||||
--label "dependencies" \
|
|
||||||
--label "dependencies-weekly-check" \
|
|
||||||
--label "dependencies-not-dependabot" \
|
|
||||||
--label "node" \
|
|
||||||
--label "javascript" \
|
|
||||||
--body-file pr_body.txt
|
|
||||||
|
|
||||||
echo "::notice title=PR Created::Successfully created Node.js version update PR on branch $branch_name"
|
|
||||||
235
.github/workflows/npm-audit-typescript.yml
vendored
235
.github/workflows/npm-audit-typescript.yml
vendored
@@ -1,235 +0,0 @@
|
|||||||
name: NPM Audit Fix with TypeScript Auto-Fix
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
npm-audit-with-ts-fix:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@v6
|
|
||||||
with:
|
|
||||||
node-version: "20"
|
|
||||||
- name: NPM install and audit fix with TypeScript auto-repair
|
|
||||||
working-directory: src/Misc/expressionFunc/hashFiles
|
|
||||||
run: |
|
|
||||||
npm install
|
|
||||||
|
|
||||||
# Check for vulnerabilities first
|
|
||||||
echo "Checking for npm vulnerabilities..."
|
|
||||||
if npm audit --audit-level=moderate; then
|
|
||||||
echo "✅ No moderate or higher vulnerabilities found"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "⚠️ Vulnerabilities found, attempting npm audit fix..."
|
|
||||||
|
|
||||||
# Attempt audit fix and capture the result
|
|
||||||
if npm audit fix; then
|
|
||||||
echo "✅ npm audit fix completed successfully"
|
|
||||||
AUDIT_FIX_STATUS="success"
|
|
||||||
else
|
|
||||||
echo "⚠️ npm audit fix failed or had issues"
|
|
||||||
AUDIT_FIX_STATUS="failed"
|
|
||||||
|
|
||||||
# Try audit fix with --force as a last resort for critical/high vulns only
|
|
||||||
echo "Checking if critical/high vulnerabilities remain..."
|
|
||||||
if ! npm audit --audit-level=high; then
|
|
||||||
echo "🚨 Critical/high vulnerabilities remain, attempting --force fix..."
|
|
||||||
if npm audit fix --force; then
|
|
||||||
echo "⚠️ npm audit fix --force completed (may have breaking changes)"
|
|
||||||
AUDIT_FIX_STATUS="force-fixed"
|
|
||||||
else
|
|
||||||
echo "❌ npm audit fix --force also failed"
|
|
||||||
AUDIT_FIX_STATUS="force-failed"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "✅ Only moderate/low vulnerabilities remain after failed fix"
|
|
||||||
AUDIT_FIX_STATUS="partial-success"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "AUDIT_FIX_STATUS=$AUDIT_FIX_STATUS" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
# Try to fix TypeScript issues automatically
|
|
||||||
echo "Attempting to fix TypeScript compatibility issues..."
|
|
||||||
|
|
||||||
# Check if build fails
|
|
||||||
if ! npm run build 2>/dev/null; then
|
|
||||||
echo "Build failed, attempting automated fixes..."
|
|
||||||
|
|
||||||
# Common fix 1: Update @types/node to latest compatible version
|
|
||||||
echo "Trying to update @types/node to latest version..."
|
|
||||||
npm update @types/node
|
|
||||||
|
|
||||||
# Common fix 2: If that doesn't work, try installing a specific known-good version
|
|
||||||
if ! npm run build 2>/dev/null; then
|
|
||||||
echo "Trying specific @types/node version..."
|
|
||||||
# Try Node 20 compatible version
|
|
||||||
npm install --save-dev @types/node@^20.0.0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Common fix 3: Clear node_modules and reinstall if still failing
|
|
||||||
if ! npm run build 2>/dev/null; then
|
|
||||||
echo "Clearing node_modules and reinstalling..."
|
|
||||||
rm -rf node_modules package-lock.json
|
|
||||||
npm install
|
|
||||||
|
|
||||||
# Re-run audit fix after clean install if it was successful before
|
|
||||||
if [[ "$AUDIT_FIX_STATUS" == "success" || "$AUDIT_FIX_STATUS" == "force-fixed" ]]; then
|
|
||||||
echo "Re-running npm audit fix after clean install..."
|
|
||||||
npm audit fix || echo "Audit fix failed on second attempt"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Common fix 4: Try updating TypeScript itself
|
|
||||||
if ! npm run build 2>/dev/null; then
|
|
||||||
echo "Trying to update TypeScript..."
|
|
||||||
npm update typescript
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Final check
|
|
||||||
if npm run build 2>/dev/null; then
|
|
||||||
echo "✅ Successfully fixed TypeScript issues automatically"
|
|
||||||
else
|
|
||||||
echo "⚠️ Could not automatically fix TypeScript issues"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "✅ Build passes after audit fix"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Create PR if changes exist
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
HUSKY: 0 # Disable husky hooks for automated commits
|
|
||||||
run: |
|
|
||||||
# Check if there are any changes
|
|
||||||
if [ -n "$(git status --porcelain)" ]; then
|
|
||||||
# Configure git
|
|
||||||
git config --global user.name "github-actions[bot]"
|
|
||||||
git config --global user.email "<41898282+github-actions[bot]@users.noreply.github.com>"
|
|
||||||
|
|
||||||
# Create branch and commit changes
|
|
||||||
branch_name="chore/npm-audit-fix-with-ts-repair"
|
|
||||||
git checkout -b "$branch_name"
|
|
||||||
|
|
||||||
# Commit with --no-verify to skip husky hooks
|
|
||||||
git commit -a -m "chore: npm audit fix with automated TypeScript compatibility fixes" --no-verify
|
|
||||||
git push --force origin "$branch_name"
|
|
||||||
|
|
||||||
# Check final build status and gather info about what was changed
|
|
||||||
build_status="✅ Build passes"
|
|
||||||
fixes_applied=""
|
|
||||||
cd src/Misc/expressionFunc/hashFiles
|
|
||||||
|
|
||||||
# Check what packages were updated
|
|
||||||
if git diff HEAD~1 package.json | grep -q "@types/node"; then
|
|
||||||
fixes_applied+="\n- Updated @types/node version for TypeScript compatibility"
|
|
||||||
fi
|
|
||||||
if git diff HEAD~1 package.json | grep -q "typescript"; then
|
|
||||||
fixes_applied+="\n- Updated TypeScript version"
|
|
||||||
fi
|
|
||||||
if git diff HEAD~1 package-lock.json | grep -q "resolved"; then
|
|
||||||
fixes_applied+="\n- Updated package dependencies via npm audit fix"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! npm run build 2>/dev/null; then
|
|
||||||
build_status="⚠️ Build fails - manual review required"
|
|
||||||
fi
|
|
||||||
cd - > /dev/null
|
|
||||||
|
|
||||||
# Create enhanced PR body using here-doc for proper formatting
|
|
||||||
audit_status_msg=""
|
|
||||||
case "$AUDIT_FIX_STATUS" in
|
|
||||||
"success")
|
|
||||||
audit_status_msg="✅ **Audit Fix**: Completed successfully"
|
|
||||||
;;
|
|
||||||
"partial-success")
|
|
||||||
audit_status_msg="⚠️ **Audit Fix**: Partial success (only moderate/low vulnerabilities remain)"
|
|
||||||
;;
|
|
||||||
"force-fixed")
|
|
||||||
audit_status_msg="⚠️ **Audit Fix**: Completed with --force (may have breaking changes)"
|
|
||||||
;;
|
|
||||||
"failed"|"force-failed")
|
|
||||||
audit_status_msg="❌ **Audit Fix**: Failed to resolve vulnerabilities"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
audit_status_msg="❓ **Audit Fix**: Status unknown"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [[ "$build_status" == *"fails"* ]]; then
|
|
||||||
cat > pr_body.txt << EOF
|
|
||||||
Automated npm audit fix with TypeScript auto-repair for hashFiles dependencies.
|
|
||||||
|
|
||||||
**Build Status**: ⚠️ Build fails - manual review required
|
|
||||||
$audit_status_msg
|
|
||||||
|
|
||||||
This workflow attempts to automatically fix TypeScript compatibility issues that may arise from npm audit fixes.
|
|
||||||
|
|
||||||
⚠️ **Manual Review Required**: The build is currently failing after automated fixes were attempted.
|
|
||||||
|
|
||||||
Common issues and solutions:
|
|
||||||
- Check for TypeScript version compatibility with Node.js types
|
|
||||||
- Review breaking changes in updated dependencies
|
|
||||||
- Consider pinning problematic dependency versions temporarily
|
|
||||||
- Review tsconfig.json for compatibility settings
|
|
||||||
|
|
||||||
**Automated Fix Strategy**:
|
|
||||||
1. Run npm audit fix with proper error handling
|
|
||||||
2. Update @types/node to latest compatible version
|
|
||||||
3. Try Node 20 specific @types/node version if needed
|
|
||||||
4. Clean reinstall dependencies if conflicts persist
|
|
||||||
5. Update TypeScript compiler if necessary
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Autogenerated by [NPM Audit Fix with TypeScript Auto-Fix Workflow](https://github.com/actions/runner/blob/main/.github/workflows/npm-audit-ts-fix.yml)
|
|
||||||
EOF
|
|
||||||
else
|
|
||||||
cat > pr_body.txt << EOF
|
|
||||||
Automated npm audit fix with TypeScript auto-repair for hashFiles dependencies.
|
|
||||||
|
|
||||||
**Build Status**: ✅ Build passes
|
|
||||||
$audit_status_msg
|
|
||||||
|
|
||||||
This workflow attempts to automatically fix TypeScript compatibility issues that may arise from npm audit fixes.
|
|
||||||
|
|
||||||
✅ **Ready to Merge**: All automated fixes were successful and the build passes.
|
|
||||||
|
|
||||||
**Automated Fix Strategy**:
|
|
||||||
1. Run npm audit fix with proper error handling
|
|
||||||
2. Update @types/node to latest compatible version
|
|
||||||
3. Try Node 20 specific @types/node version if needed
|
|
||||||
4. Clean reinstall dependencies if conflicts persist
|
|
||||||
5. Update TypeScript compiler if necessary
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Autogenerated by [NPM Audit Fix with TypeScript Auto-Fix Workflow](https://github.com/actions/runner/blob/main/.github/workflows/npm-audit-ts-fix.yml)
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "$fixes_applied" ]; then
|
|
||||||
# Add the fixes applied section to the file
|
|
||||||
sed -i "/This workflow attempts/a\\
|
|
||||||
\\
|
|
||||||
**Automated Fixes Applied**:$fixes_applied" pr_body.txt
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create PR with appropriate labels
|
|
||||||
labels="dependencies,dependencies-not-dependabot,typescript,npm,security"
|
|
||||||
if [[ "$build_status" == *"fails"* ]]; then
|
|
||||||
labels="dependencies,dependencies-not-dependabot,typescript,npm,security,needs-manual-review"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create PR
|
|
||||||
gh pr create -B main -H "$branch_name" \
|
|
||||||
--title "chore: npm audit fix with TypeScript auto-repair" \
|
|
||||||
--label "$labels" \
|
|
||||||
--body-file pr_body.txt
|
|
||||||
else
|
|
||||||
echo "No changes to commit"
|
|
||||||
fi
|
|
||||||
137
.github/workflows/npm-audit.yml
vendored
137
.github/workflows/npm-audit.yml
vendored
@@ -1,137 +0,0 @@
|
|||||||
name: NPM Audit Fix
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: "0 7 * * 1" # Weekly on Monday at 7 AM UTC
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
npm-audit:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@v6
|
|
||||||
with:
|
|
||||||
node-version: "20"
|
|
||||||
|
|
||||||
- name: NPM install and audit fix
|
|
||||||
working-directory: src/Misc/expressionFunc/hashFiles
|
|
||||||
run: |
|
|
||||||
npm install
|
|
||||||
|
|
||||||
# Check what vulnerabilities exist
|
|
||||||
echo "=== Checking current vulnerabilities ==="
|
|
||||||
npm audit || true
|
|
||||||
|
|
||||||
# Apply audit fix --force to get security updates
|
|
||||||
echo "=== Applying npm audit fix --force ==="
|
|
||||||
npm audit fix --force
|
|
||||||
|
|
||||||
# Test if build still works and set status
|
|
||||||
echo "=== Testing build compatibility ==="
|
|
||||||
if npm run all; then
|
|
||||||
echo "✅ Build successful after audit fix"
|
|
||||||
echo "AUDIT_FIX_STATUS=success" >> $GITHUB_ENV
|
|
||||||
else
|
|
||||||
echo "❌ Build failed after audit fix - will create PR with fix instructions"
|
|
||||||
echo "AUDIT_FIX_STATUS=build_failed" >> $GITHUB_ENV
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Create PR if changes exist
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
# Check if there are any changes
|
|
||||||
if [ -n "$(git status --porcelain)" ]; then
|
|
||||||
# Configure git
|
|
||||||
git config --global user.name "github-actions[bot]"
|
|
||||||
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
||||||
|
|
||||||
# Create branch and commit changes
|
|
||||||
branch_name="chore/npm-audit-fix-$(date +%Y%m%d)"
|
|
||||||
git checkout -b "$branch_name"
|
|
||||||
git add .
|
|
||||||
git commit -m "chore: npm audit fix for hashFiles dependencies" --no-verify
|
|
||||||
git push origin "$branch_name"
|
|
||||||
|
|
||||||
# Create PR body based on what actually happened
|
|
||||||
if [ "$AUDIT_FIX_STATUS" = "success" ]; then
|
|
||||||
cat > pr_body.txt << 'EOF'
|
|
||||||
Automated npm audit fix for security vulnerabilities in hashFiles dependencies.
|
|
||||||
|
|
||||||
**✅ Full Fix Applied Successfully**
|
|
||||||
This update addresses npm security advisories and ensures dependencies are secure and up-to-date.
|
|
||||||
|
|
||||||
**Changes made:**
|
|
||||||
- Applied `npm audit fix --force` to resolve security vulnerabilities
|
|
||||||
- Updated package-lock.json with security patches
|
|
||||||
- Verified build compatibility with `npm run all`
|
|
||||||
|
|
||||||
**Next steps:**
|
|
||||||
- Review the dependency changes
|
|
||||||
- Verify the hashFiles functionality still works as expected
|
|
||||||
- Merge when ready
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Autogenerated by [NPM Audit Fix Workflow](https://github.com/actions/runner/blob/main/.github/workflows/npm-audit.yml)
|
|
||||||
EOF
|
|
||||||
elif [ "$AUDIT_FIX_STATUS" = "build_failed" ]; then
|
|
||||||
cat > pr_body.txt << 'EOF'
|
|
||||||
Automated npm audit fix for security vulnerabilities in hashFiles dependencies.
|
|
||||||
|
|
||||||
**⚠️ Security Fixes Applied - Build Issues Need Manual Resolution**
|
|
||||||
This update applies important security patches but causes build failures that require manual fixes.
|
|
||||||
|
|
||||||
**Changes made:**
|
|
||||||
- Applied `npm audit fix --force` to resolve security vulnerabilities
|
|
||||||
- Updated package-lock.json with security patches
|
|
||||||
|
|
||||||
**⚠️ Build Issues Detected:**
|
|
||||||
The build fails after applying security fixes, likely due to TypeScript compatibility issues with updated `@types/node`.
|
|
||||||
|
|
||||||
**Required Manual Fixes:**
|
|
||||||
1. Review TypeScript compilation errors in the build output
|
|
||||||
2. Update TypeScript configuration if needed
|
|
||||||
3. Consider pinning `@types/node` to a compatible version
|
|
||||||
4. Run `npm run all` locally to verify fixes
|
|
||||||
|
|
||||||
**Next steps:**
|
|
||||||
- **DO NOT merge until build issues are resolved**
|
|
||||||
- Apply manual fixes for TypeScript compatibility
|
|
||||||
- Test the hashFiles functionality still works as expected
|
|
||||||
- Merge when build passes
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Autogenerated by [NPM Audit Fix Workflow](https://github.com/actions/runner/blob/main/.github/workflows/npm-audit.yml)
|
|
||||||
EOF
|
|
||||||
else
|
|
||||||
# Fallback case
|
|
||||||
cat > pr_body.txt << 'EOF'
|
|
||||||
Automated npm audit attempted for security vulnerabilities in hashFiles dependencies.
|
|
||||||
|
|
||||||
**ℹ️ No Changes Applied**
|
|
||||||
No security vulnerabilities were found or no changes were needed.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Autogenerated by [NPM Audit Fix Workflow](https://github.com/actions/runner/blob/main/.github/workflows/npm-audit.yml)
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create PR
|
|
||||||
gh pr create -B main -H "$branch_name" \
|
|
||||||
--title "chore: npm audit fix for hashFiles dependencies" \
|
|
||||||
--label "dependencies" \
|
|
||||||
--label "dependencies-weekly-check" \
|
|
||||||
--label "dependencies-not-dependabot" \
|
|
||||||
--label "npm" \
|
|
||||||
--label "typescript" \
|
|
||||||
--label "security" \
|
|
||||||
--body-file pr_body.txt
|
|
||||||
else
|
|
||||||
echo "✅ No changes to commit - npm audit fix did not modify any files"
|
|
||||||
fi
|
|
||||||
223
.github/workflows/release.yml
vendored
223
.github/workflows/release.yml
vendored
@@ -5,21 +5,22 @@ on:
|
|||||||
push:
|
push:
|
||||||
paths:
|
paths:
|
||||||
- releaseVersion
|
- releaseVersion
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check:
|
check:
|
||||||
if: startsWith(github.ref, 'refs/heads/releases/') || github.ref == 'refs/heads/main'
|
if: startsWith(github.ref, 'refs/heads/releases/') || github.ref == 'refs/heads/main'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
# Make sure ./releaseVersion match ./src/runnerversion
|
# Make sure ./releaseVersion match ./src/runnerversion
|
||||||
# Query GitHub release ensure version is not used
|
# Query GitHub release ensure version is not used
|
||||||
- name: Check version
|
- name: Check version
|
||||||
uses: actions/github-script@v8.0.0
|
uses: actions/github-script@0.3.0
|
||||||
with:
|
with:
|
||||||
github-token: ${{secrets.GITHUB_TOKEN}}
|
github-token: ${{secrets.GITHUB_TOKEN}}
|
||||||
script: |
|
script: |
|
||||||
|
const core = require('@actions/core')
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const runnerVersion = fs.readFileSync('${{ github.workspace }}/src/runnerversion', 'utf8').replace(/\n$/g, '')
|
const runnerVersion = fs.readFileSync('${{ github.workspace }}/src/runnerversion', 'utf8').replace(/\n$/g, '')
|
||||||
const releaseVersion = fs.readFileSync('${{ github.workspace }}/releaseVersion', 'utf8').replace(/\n$/g, '')
|
const releaseVersion = fs.readFileSync('${{ github.workspace }}/releaseVersion', 'utf8').replace(/\n$/g, '')
|
||||||
@@ -29,7 +30,7 @@ jobs:
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const release = await github.rest.repos.getReleaseByTag({
|
const release = await github.repos.getReleaseByTag({
|
||||||
owner: '${{ github.event.repository.owner.name }}',
|
owner: '${{ github.event.repository.owner.name }}',
|
||||||
repo: '${{ github.event.repository.name }}',
|
repo: '${{ github.event.repository.name }}',
|
||||||
tag: 'v' + runnerVersion
|
tag: 'v' + runnerVersion
|
||||||
@@ -41,20 +42,12 @@ jobs:
|
|||||||
throw e
|
throw e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
build:
|
build:
|
||||||
needs: check
|
needs: check
|
||||||
outputs:
|
|
||||||
linux-x64-sha: ${{ steps.sha.outputs.linux-x64-sha256 }}
|
|
||||||
linux-arm64-sha: ${{ steps.sha.outputs.linux-arm64-sha256 }}
|
|
||||||
linux-arm-sha: ${{ steps.sha.outputs.linux-arm-sha256 }}
|
|
||||||
win-x64-sha: ${{ steps.sha.outputs.win-x64-sha256 }}
|
|
||||||
win-arm64-sha: ${{ steps.sha.outputs.win-arm64-sha256 }}
|
|
||||||
osx-x64-sha: ${{ steps.sha.outputs.osx-x64-sha256 }}
|
|
||||||
osx-arm64-sha: ${{ steps.sha.outputs.osx-arm64-sha256 }}
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, osx-x64, osx-arm64, win-arm64 ]
|
runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, osx-x64 ]
|
||||||
include:
|
include:
|
||||||
- runtime: linux-x64
|
- runtime: linux-x64
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
@@ -72,21 +65,13 @@ jobs:
|
|||||||
os: macOS-latest
|
os: macOS-latest
|
||||||
devScript: ./dev.sh
|
devScript: ./dev.sh
|
||||||
|
|
||||||
- runtime: osx-arm64
|
|
||||||
os: macOS-latest
|
|
||||||
devScript: ./dev.sh
|
|
||||||
|
|
||||||
- runtime: win-x64
|
- runtime: win-x64
|
||||||
os: windows-latest
|
os: windows-latest
|
||||||
devScript: ./dev
|
devScript: ./dev
|
||||||
|
|
||||||
- runtime: win-arm64
|
|
||||||
os: windows-latest
|
|
||||||
devScript: ./dev
|
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v1
|
||||||
|
|
||||||
# Build runner layout
|
# Build runner layout
|
||||||
- name: Build & Layout Release
|
- name: Build & Layout Release
|
||||||
@@ -94,6 +79,13 @@ jobs:
|
|||||||
${{ matrix.devScript }} layout Release ${{ matrix.runtime }}
|
${{ matrix.devScript }} layout Release ${{ matrix.runtime }}
|
||||||
working-directory: src
|
working-directory: src
|
||||||
|
|
||||||
|
# Run tests
|
||||||
|
- name: L0
|
||||||
|
run: |
|
||||||
|
${{ matrix.devScript }} test
|
||||||
|
working-directory: src
|
||||||
|
if: matrix.runtime != 'linux-arm64' && matrix.runtime != 'linux-arm'
|
||||||
|
|
||||||
# Create runner package tar.gz/zip
|
# Create runner package tar.gz/zip
|
||||||
- name: Package Release
|
- name: Package Release
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request'
|
||||||
@@ -101,105 +93,44 @@ jobs:
|
|||||||
${{ matrix.devScript }} package Release ${{ matrix.runtime }}
|
${{ matrix.devScript }} package Release ${{ matrix.runtime }}
|
||||||
working-directory: src
|
working-directory: src
|
||||||
|
|
||||||
# compute shas and set as job outputs to use in release notes
|
|
||||||
- run: brew install coreutils #needed for shasum util
|
|
||||||
if: ${{ matrix.os == 'macOS-latest' }}
|
|
||||||
name: Install Dependencies for SHA Calculation (osx)
|
|
||||||
- run: |
|
|
||||||
file=$(ls)
|
|
||||||
sha=$(sha256sum $file | awk '{ print $1 }')
|
|
||||||
echo "Computed sha256: $sha for $file"
|
|
||||||
echo "${{matrix.runtime}}-sha256=$sha" >> $GITHUB_OUTPUT
|
|
||||||
shell: bash
|
|
||||||
id: sha
|
|
||||||
name: Compute SHA256
|
|
||||||
working-directory: _package
|
|
||||||
|
|
||||||
# Upload runner package tar.gz/zip as artifact.
|
# Upload runner package tar.gz/zip as artifact.
|
||||||
|
# Since each package name is unique, so we don't need to put ${{matrix}} info into artifact name
|
||||||
- name: Publish Artifact
|
- name: Publish Artifact
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request'
|
||||||
uses: actions/upload-artifact@v5
|
uses: actions/upload-artifact@v1
|
||||||
with:
|
with:
|
||||||
name: runner-packages-${{ matrix.runtime }}
|
name: runner-packages
|
||||||
path: |
|
path: _package
|
||||||
_package
|
|
||||||
|
|
||||||
release:
|
release:
|
||||||
needs: build
|
needs: build
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
# Download runner package tar.gz/zip produced by 'build' job
|
# Download runner package tar.gz/zip produced by 'build' job
|
||||||
- name: Download Artifact (win-x64)
|
- name: Download Artifact
|
||||||
uses: actions/download-artifact@v6
|
uses: actions/download-artifact@v1
|
||||||
with:
|
with:
|
||||||
name: runner-packages-win-x64
|
name: runner-packages
|
||||||
path: ./
|
|
||||||
- name: Download Artifact (win-arm64)
|
|
||||||
uses: actions/download-artifact@v6
|
|
||||||
with:
|
|
||||||
name: runner-packages-win-arm64
|
|
||||||
path: ./
|
|
||||||
- name: Download Artifact (osx-x64)
|
|
||||||
uses: actions/download-artifact@v6
|
|
||||||
with:
|
|
||||||
name: runner-packages-osx-x64
|
|
||||||
path: ./
|
|
||||||
- name: Download Artifact (osx-arm64)
|
|
||||||
uses: actions/download-artifact@v6
|
|
||||||
with:
|
|
||||||
name: runner-packages-osx-arm64
|
|
||||||
path: ./
|
|
||||||
- name: Download Artifact (linux-x64)
|
|
||||||
uses: actions/download-artifact@v6
|
|
||||||
with:
|
|
||||||
name: runner-packages-linux-x64
|
|
||||||
path: ./
|
|
||||||
- name: Download Artifact (linux-arm)
|
|
||||||
uses: actions/download-artifact@v6
|
|
||||||
with:
|
|
||||||
name: runner-packages-linux-arm
|
|
||||||
path: ./
|
|
||||||
- name: Download Artifact (linux-arm64)
|
|
||||||
uses: actions/download-artifact@v6
|
|
||||||
with:
|
|
||||||
name: runner-packages-linux-arm64
|
|
||||||
path: ./
|
path: ./
|
||||||
|
|
||||||
# Create ReleaseNote file
|
# Create ReleaseNote file
|
||||||
- name: Create ReleaseNote
|
- name: Create ReleaseNote
|
||||||
id: releaseNote
|
id: releaseNote
|
||||||
uses: actions/github-script@v8.0.0
|
uses: actions/github-script@0.3.0
|
||||||
with:
|
with:
|
||||||
github-token: ${{secrets.GITHUB_TOKEN}}
|
github-token: ${{secrets.GITHUB_TOKEN}}
|
||||||
script: |
|
script: |
|
||||||
|
const core = require('@actions/core')
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const runnerVersion = fs.readFileSync('${{ github.workspace }}/src/runnerversion', 'utf8').replace(/\n$/g, '')
|
const runnerVersion = fs.readFileSync('${{ github.workspace }}/src/runnerversion', 'utf8').replace(/\n$/g, '')
|
||||||
var releaseNote = fs.readFileSync('${{ github.workspace }}/releaseNote.md', 'utf8').replace(/<RUNNER_VERSION>/g, runnerVersion)
|
const releaseNote = fs.readFileSync('${{ github.workspace }}/releaseNote.md', 'utf8').replace(/<RUNNER_VERSION>/g, runnerVersion)
|
||||||
releaseNote = releaseNote.replace(/<WIN_X64_SHA>/g, '${{needs.build.outputs.win-x64-sha}}')
|
|
||||||
releaseNote = releaseNote.replace(/<WIN_ARM64_SHA>/g, '${{needs.build.outputs.win-arm64-sha}}')
|
|
||||||
releaseNote = releaseNote.replace(/<OSX_X64_SHA>/g, '${{needs.build.outputs.osx-x64-sha}}')
|
|
||||||
releaseNote = releaseNote.replace(/<OSX_ARM64_SHA>/g, '${{needs.build.outputs.osx-arm64-sha}}')
|
|
||||||
releaseNote = releaseNote.replace(/<LINUX_X64_SHA>/g, '${{needs.build.outputs.linux-x64-sha}}')
|
|
||||||
releaseNote = releaseNote.replace(/<LINUX_ARM_SHA>/g, '${{needs.build.outputs.linux-arm-sha}}')
|
|
||||||
releaseNote = releaseNote.replace(/<LINUX_ARM64_SHA>/g, '${{needs.build.outputs.linux-arm64-sha}}')
|
|
||||||
console.log(releaseNote)
|
console.log(releaseNote)
|
||||||
core.setOutput('version', runnerVersion);
|
core.setOutput('version', runnerVersion);
|
||||||
core.setOutput('note', releaseNote);
|
core.setOutput('note', releaseNote);
|
||||||
|
|
||||||
- name: Validate Packages HASH
|
|
||||||
run: |
|
|
||||||
ls -l
|
|
||||||
echo "${{needs.build.outputs.win-x64-sha}} actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}.zip" | shasum -a 256 -c
|
|
||||||
echo "${{needs.build.outputs.win-arm64-sha}} actions-runner-win-arm64-${{ steps.releaseNote.outputs.version }}.zip" | shasum -a 256 -c
|
|
||||||
echo "${{needs.build.outputs.osx-x64-sha}} actions-runner-osx-x64-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c
|
|
||||||
echo "${{needs.build.outputs.osx-arm64-sha}} actions-runner-osx-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c
|
|
||||||
echo "${{needs.build.outputs.linux-x64-sha}} actions-runner-linux-x64-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c
|
|
||||||
echo "${{needs.build.outputs.linux-arm-sha}} actions-runner-linux-arm-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c
|
|
||||||
echo "${{needs.build.outputs.linux-arm64-sha}} actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c
|
|
||||||
|
|
||||||
# Create GitHub release
|
# Create GitHub release
|
||||||
- uses: actions/create-release@master
|
- uses: actions/create-release@master
|
||||||
id: createRelease
|
id: createRelease
|
||||||
@@ -211,10 +142,11 @@ jobs:
|
|||||||
release_name: "v${{ steps.releaseNote.outputs.version }}"
|
release_name: "v${{ steps.releaseNote.outputs.version }}"
|
||||||
body: |
|
body: |
|
||||||
${{ steps.releaseNote.outputs.note }}
|
${{ steps.releaseNote.outputs.note }}
|
||||||
|
prerelease: true
|
||||||
|
|
||||||
# Upload release assets (full runner packages)
|
# Upload release assets
|
||||||
- name: Upload Release Asset (win-x64)
|
- name: Upload Release Asset (win-x64)
|
||||||
uses: actions/upload-release-asset@v1.0.2
|
uses: actions/upload-release-asset@v1.0.1
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
@@ -223,18 +155,8 @@ jobs:
|
|||||||
asset_name: actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}.zip
|
asset_name: actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}.zip
|
||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
- name: Upload Release Asset (win-arm64)
|
|
||||||
uses: actions/upload-release-asset@v1.0.2
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
|
||||||
asset_path: ${{ github.workspace }}/actions-runner-win-arm64-${{ steps.releaseNote.outputs.version }}.zip
|
|
||||||
asset_name: actions-runner-win-arm64-${{ steps.releaseNote.outputs.version }}.zip
|
|
||||||
asset_content_type: application/octet-stream
|
|
||||||
|
|
||||||
- name: Upload Release Asset (linux-x64)
|
- name: Upload Release Asset (linux-x64)
|
||||||
uses: actions/upload-release-asset@v1.0.2
|
uses: actions/upload-release-asset@v1.0.1
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
@@ -244,7 +166,7 @@ jobs:
|
|||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
- name: Upload Release Asset (osx-x64)
|
- name: Upload Release Asset (osx-x64)
|
||||||
uses: actions/upload-release-asset@v1.0.2
|
uses: actions/upload-release-asset@v1.0.1
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
@@ -253,18 +175,8 @@ jobs:
|
|||||||
asset_name: actions-runner-osx-x64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
asset_name: actions-runner-osx-x64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
- name: Upload Release Asset (osx-arm64)
|
|
||||||
uses: actions/upload-release-asset@v1.0.2
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
|
||||||
asset_path: ${{ github.workspace }}/actions-runner-osx-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
|
||||||
asset_name: actions-runner-osx-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
|
||||||
asset_content_type: application/octet-stream
|
|
||||||
|
|
||||||
- name: Upload Release Asset (linux-arm)
|
- name: Upload Release Asset (linux-arm)
|
||||||
uses: actions/upload-release-asset@v1.0.2
|
uses: actions/upload-release-asset@v1.0.1
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
@@ -274,72 +186,11 @@ jobs:
|
|||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
- name: Upload Release Asset (linux-arm64)
|
- name: Upload Release Asset (linux-arm64)
|
||||||
uses: actions/upload-release-asset@v1.0.2
|
uses: actions/upload-release-asset@v1.0.1
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
upload_url: ${{ steps.createRelease.outputs.upload_url }}
|
||||||
asset_path: ${{ github.workspace }}/actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
asset_path: ${{ github.workspace }}/actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
||||||
asset_name: actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
asset_name: actions-runner-linux-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz
|
||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
publish-image:
|
|
||||||
needs: release
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
packages: write
|
|
||||||
id-token: write
|
|
||||||
attestations: write
|
|
||||||
env:
|
|
||||||
REGISTRY: ghcr.io
|
|
||||||
IMAGE_NAME: ${{ github.repository_owner }}/actions-runner
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
|
|
||||||
- name: Compute image version
|
|
||||||
id: image
|
|
||||||
uses: actions/github-script@v8.0.0
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const fs = require('fs');
|
|
||||||
const runnerVersion = fs.readFileSync('${{ github.workspace }}/releaseVersion', 'utf8').replace(/\n$/g, '')
|
|
||||||
console.log(`Using runner version ${runnerVersion}`)
|
|
||||||
core.setOutput('version', runnerVersion);
|
|
||||||
|
|
||||||
- name: Setup Docker buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
|
|
||||||
- name: Log into registry ${{ env.REGISTRY }}
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: ${{ env.REGISTRY }}
|
|
||||||
username: ${{ github.actor }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Build and push Docker image
|
|
||||||
id: build-and-push
|
|
||||||
uses: docker/build-push-action@v6
|
|
||||||
with:
|
|
||||||
context: ./images
|
|
||||||
platforms: |
|
|
||||||
linux/amd64
|
|
||||||
linux/arm64
|
|
||||||
tags: |
|
|
||||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.image.outputs.version }}
|
|
||||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
|
||||||
build-args: |
|
|
||||||
RUNNER_VERSION=${{ steps.image.outputs.version }}
|
|
||||||
push: true
|
|
||||||
labels: |
|
|
||||||
org.opencontainers.image.source=${{github.server_url}}/${{github.repository}}
|
|
||||||
org.opencontainers.image.description=https://github.com/actions/runner/releases/tag/v${{ steps.image.outputs.version }}
|
|
||||||
org.opencontainers.image.licenses=MIT
|
|
||||||
|
|
||||||
- name: Generate attestation
|
|
||||||
uses: actions/attest-build-provenance@v3
|
|
||||||
with:
|
|
||||||
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
|
||||||
subject-digest: ${{ steps.build-and-push.outputs.digest }}
|
|
||||||
push-to-registry: true
|
|
||||||
16
.github/workflows/stale-bot.yml
vendored
16
.github/workflows/stale-bot.yml
vendored
@@ -1,16 +0,0 @@
|
|||||||
name: Stale Bot
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0 * * 1' # every monday at midnight
|
|
||||||
jobs:
|
|
||||||
stale:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/stale@v10
|
|
||||||
with:
|
|
||||||
stale-issue-message: "This issue is stale because it has been open 365 days with no activity. Remove stale label or comment or this will be closed in 15 days."
|
|
||||||
close-issue-message: "This issue was closed because it has been stalled for 15 days with no activity."
|
|
||||||
exempt-issue-labels: "keep"
|
|
||||||
days-before-stale: 365
|
|
||||||
days-before-close: 15
|
|
||||||
12
.gitignore
vendored
12
.gitignore
vendored
@@ -8,23 +8,21 @@
|
|||||||
**/*.xproj
|
**/*.xproj
|
||||||
**/*.xproj.user
|
**/*.xproj.user
|
||||||
**/.vs
|
**/.vs
|
||||||
|
**/.vscode
|
||||||
**/*.error
|
**/*.error
|
||||||
**/*.json.pretty
|
**/*.json.pretty
|
||||||
.idea/
|
.idea/
|
||||||
.vscode
|
|
||||||
!.vscode/launch.json
|
|
||||||
!.vscode/tasks.json
|
|
||||||
|
|
||||||
# output
|
# output
|
||||||
node_modules
|
node_modules
|
||||||
_downloads
|
_downloads
|
||||||
_layout
|
_layout
|
||||||
_layout_trims
|
|
||||||
_package
|
_package
|
||||||
_package_trims
|
|
||||||
_dotnetsdk
|
_dotnetsdk
|
||||||
TestResults
|
TestResults
|
||||||
TestLogs
|
TestLogs
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.mono
|
**/*.DotSettings.user
|
||||||
**/*.DotSettings.user
|
|
||||||
|
#generated
|
||||||
|
src/Runner.Sdk/BuildConstants.cs
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
cd src/Misc/expressionFunc/hashFiles && npx lint-staged
|
|
||||||
58
.vscode/launch.json
vendored
58
.vscode/launch.json
vendored
@@ -1,58 +0,0 @@
|
|||||||
{
|
|
||||||
"version": "0.2.0",
|
|
||||||
"configurations": [
|
|
||||||
{
|
|
||||||
"name": "Run [build]",
|
|
||||||
"type": "coreclr",
|
|
||||||
"request": "launch",
|
|
||||||
"preLaunchTask": "build runner layout",
|
|
||||||
"program": "${workspaceFolder}/_layout/bin/Runner.Listener",
|
|
||||||
"args": [
|
|
||||||
"run"
|
|
||||||
],
|
|
||||||
"cwd": "${workspaceFolder}/src",
|
|
||||||
"console": "integratedTerminal",
|
|
||||||
"requireExactSource": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Run",
|
|
||||||
"type": "coreclr",
|
|
||||||
"request": "launch",
|
|
||||||
"program": "${workspaceFolder}/_layout/bin/Runner.Listener",
|
|
||||||
"args": [
|
|
||||||
"run"
|
|
||||||
],
|
|
||||||
"cwd": "${workspaceFolder}/src",
|
|
||||||
"console": "integratedTerminal",
|
|
||||||
"requireExactSource": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Configure",
|
|
||||||
"type": "coreclr",
|
|
||||||
"request": "launch",
|
|
||||||
"preLaunchTask": "create runner layout",
|
|
||||||
"program": "${workspaceFolder}/_layout/bin/Runner.Listener",
|
|
||||||
"args": [
|
|
||||||
"configure"
|
|
||||||
],
|
|
||||||
"cwd": "${workspaceFolder}/src",
|
|
||||||
"console": "integratedTerminal",
|
|
||||||
"requireExactSource": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Debug Worker",
|
|
||||||
"type": "coreclr",
|
|
||||||
"request": "attach",
|
|
||||||
"processName": "Runner.Worker",
|
|
||||||
"requireExactSource": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Attach Debugger",
|
|
||||||
"type": "coreclr",
|
|
||||||
"request": "attach",
|
|
||||||
"processId": "${command:pickProcess}",
|
|
||||||
"requireExactSource": false
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
33
.vscode/tasks.json
vendored
33
.vscode/tasks.json
vendored
@@ -1,33 +0,0 @@
|
|||||||
{
|
|
||||||
"version": "2.0.0",
|
|
||||||
"tasks": [
|
|
||||||
{
|
|
||||||
"label": "create runner layout",
|
|
||||||
"detail": "Build and Copy all projects, scripts and external dependencies to _layout from src (run this the first time or after deleting _layout)",
|
|
||||||
"command": "./dev.sh",
|
|
||||||
"windows": {
|
|
||||||
"command": "dev.cmd"
|
|
||||||
},
|
|
||||||
"args": [
|
|
||||||
"layout"
|
|
||||||
],
|
|
||||||
"options": {
|
|
||||||
"cwd": "${workspaceFolder}/src"
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "build runner layout",
|
|
||||||
"detail": "Build and Copy all projects to _layout from src (run this on code change)",
|
|
||||||
"command": "./dev.sh",
|
|
||||||
"windows": {
|
|
||||||
"command": "dev.cmd"
|
|
||||||
},
|
|
||||||
"args": [
|
|
||||||
"build"
|
|
||||||
],
|
|
||||||
"options": {
|
|
||||||
"cwd": "${workspaceFolder}/src"
|
|
||||||
},
|
|
||||||
}
|
|
||||||
],
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
* @actions/actions-runtime
|
|
||||||
18
README.md
18
README.md
@@ -20,20 +20,6 @@ Runner releases:
|
|||||||
|
|
||||||
 [Pre-reqs](docs/start/envlinux.md) | [Download](https://github.com/actions/runner/releases)
|
 [Pre-reqs](docs/start/envlinux.md) | [Download](https://github.com/actions/runner/releases)
|
||||||
|
|
||||||
### Note
|
## Contribute
|
||||||
|
|
||||||
Thank you for your interest in this GitHub repo, however, right now we are not taking contributions.
|
We accept contributions in the form of issues and pull requests. [Read more here](docs/contribute.md) before contributing.
|
||||||
|
|
||||||
We continue to focus our resources on strategic areas that help our customers be successful while making developers' lives easier. While GitHub Actions remains a key part of this vision, we are allocating resources towards other areas of Actions and are not taking contributions to this repository at this time. The GitHub public roadmap is the best place to follow along for any updates on features we’re working on and what stage they’re in.
|
|
||||||
|
|
||||||
We are taking the following steps to better direct requests related to GitHub Actions, including:
|
|
||||||
|
|
||||||
1. We will be directing questions and support requests to our [Community Discussions area](https://github.com/orgs/community/discussions/categories/actions)
|
|
||||||
|
|
||||||
2. High Priority bugs can be reported through Community Discussions or you can report these to our support team https://support.github.com/contact/bug-report.
|
|
||||||
|
|
||||||
3. Security Issues should be handled as per our [security.md](security.md)
|
|
||||||
|
|
||||||
We will still provide security updates for this project and fix major breaking changes during this time.
|
|
||||||
|
|
||||||
You are welcome to still raise bugs in this repo.
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# ADR 263: Self-Hosted Runner Proxies
|
# ADR 263: Self Hosted Runner Proxies
|
||||||
|
|
||||||
**Date**: 2019-11-13
|
**Date**: 2019-11-13
|
||||||
|
|
||||||
@@ -6,13 +6,13 @@
|
|||||||
|
|
||||||
## Context
|
## Context
|
||||||
|
|
||||||
- Proxy support is required for some enterprises and organizations to start using their own self-hosted runners
|
- Proxy support is required for some enterprises and organizations to start using their own self hosted runners
|
||||||
- While there is not a standard convention, many applications support setting proxies via the environment variables `http_proxy`, `https_proxy`, `no_proxy`, such as curl, wget, perl, python, docker, git, and R
|
- While there is not a standard convention, many applications support setting proxies via the environmental variables `http_proxy`, `https_proxy`, `no_proxy`, such as curl, wget, perl, python, docker, git, R, ect
|
||||||
- Some of these applications use `HTTPS_PROXY` versus `https_proxy`, but most understand or primarily support the lowercase variant
|
- Some of these applications use `HTTPS_PROXY` versus `https_proxy`, but most understand or primarily support the lowercase variant
|
||||||
|
|
||||||
## Decision
|
## Decision
|
||||||
|
|
||||||
We will update the Runner to use the conventional environment variables for proxies: `http_proxy`, `https_proxy`, and `no_proxy` if they are set.
|
We will update the Runner to use the conventional environment variables for proxies: `http_proxy`, `https_proxy` and `no_proxy` if they are set.
|
||||||
These are described in detail below:
|
These are described in detail below:
|
||||||
- `https_proxy` a proxy URL for all https traffic. It may contain basic authentication credentials. For example:
|
- `https_proxy` a proxy URL for all https traffic. It may contain basic authentication credentials. For example:
|
||||||
- http://proxy.com
|
- http://proxy.com
|
||||||
@@ -22,20 +22,20 @@ These are described in detail below:
|
|||||||
- http://proxy.com
|
- http://proxy.com
|
||||||
- http://127.0.0.1:8080
|
- http://127.0.0.1:8080
|
||||||
- http://user:password@proxy.com
|
- http://user:password@proxy.com
|
||||||
- `no_proxy` a comma-separated list of hosts that should not use the proxy. An optional port may be specified. For example:
|
- `no_proxy` a comma seperated list of hosts that should not use the proxy. An optional port may be specified
|
||||||
- `google.com`
|
- `google.com`
|
||||||
- `yahoo.com:443`
|
- `yahoo.com:443`
|
||||||
- `google.com,bing.com`
|
- `google.com,bing.com`
|
||||||
|
|
||||||
We won't use `http_proxy` for https traffic when `https_proxy` is not set, this behavior lines up with any libcurl based tools (curl, git) and wget.
|
We won't use `http_proxy` for https traffic when `https_proxy` is not set, this behavior lines up with any libcurl based tools (curl, git) and wget.
|
||||||
Otherwise, action authors and workflow users need to adjust to differences between the runner proxy convention, and tools used by their actions and scripts.
|
Otherwise action authors and workflow users need to adjust to differences between the runner proxy convention, and tools used by their actions and scripts.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
Customer sets `http_proxy=http://127.0.0.1:8888` and configures the runner against `https://github.com/owner/repo`, with the `https_proxy` -> `http_proxy` fallback, the runner will connect to the server without any problem. However, if a user runs `git push` to `https://github.com/owner/repo`, `git` won't use the proxy since it requires `https_proxy` to be set for any https traffic.
|
Customer set `http_proxy=http://127.0.0.1:8888` and configure the runner against `https://github.com/owner/repo`, with the `https_proxy` -> `http_proxy` fallback, the runner will connect to server without any problem. However, if user runs `git push` to `https://github.com/owner/repo`, `git` won't use the proxy since it require `https_proxy` to be set for any https traffic.
|
||||||
|
|
||||||
> `golang`, `node.js`, and other dev tools from the Linux community use `http_proxy` for both http and https traffic based on my research.
|
> `golang`, `node.js` and other dev tools from the linux community use `http_proxy` for both http and https traffic base on my research.
|
||||||
|
|
||||||
A majority of our users are using Linux where these variables are commonly required to be set by various programs. By reading these values, we simplify the process for self-hosted runners to set up a proxy and expose it in a way users are already familiar with.
|
A majority of our users are using Linux where these variables are commonly required to be set by various programs. By reading these values, we simplify the process for self hosted runners to set up proxy, and expose it in a way users are already familiar with.
|
||||||
|
|
||||||
A password provided for a proxy will be masked in the logs.
|
A password provided for a proxy will be masked in the logs.
|
||||||
|
|
||||||
@@ -43,19 +43,19 @@ We will support the lowercase and uppercase variants, with lowercase taking prio
|
|||||||
|
|
||||||
### No Proxy Format
|
### No Proxy Format
|
||||||
|
|
||||||
While exact implementations are different per application on handling `no_proxy` env, most applications accept a comma-separated list of hosts. Some accept wildcard characters (`*`). We are going to do exact case-insensitive matches, and not support wildcards at this time.
|
While exact implementations are different per application on handle `no_proxy` env, most applications accept a comma separated list of hosts. Some accept wildcard characters (*). We are going to do exact case-insentive matches, and not support wildcards at this time.
|
||||||
For example:
|
For example:
|
||||||
- `example.com` will match `example.com`, `foo.example.com`, and `foo.bar.example.com`
|
- example.com will match example.com, foo.example.com, foo.bar.example.com
|
||||||
- `foo.example.com` will match `bar.foo.example.com` and `foo.example.com`
|
- foo.example.com will match bar.foo.example.com and foo.example.com
|
||||||
|
|
||||||
We will not support IP addresses for `no_proxy`, only hostnames.
|
We will not support IP addresses for `no_proxy`, only hostnames.
|
||||||
|
|
||||||
## Consequences
|
## Consequences
|
||||||
|
|
||||||
1. Enterprises and organizations needing proxy support will be able to embrace self-hosted runners
|
1. Enterprises and organizations needing proxy support will be able to embrace self hosted runners
|
||||||
2. Users will need to set these environment variables before configuring the runner in order to use a proxy when configuring
|
2. Users will need to set these environmental variables before configuring the runner in order to use a proxy when configuring
|
||||||
3. The runner will read from the environment variables during config and runtime and use the provided proxy if it exists
|
3. The runner will read from the environmental variables during config and runtime and use the provided proxy if it exists
|
||||||
4. Users may need to pass these environment variables into other applications if they do not natively take these variables
|
4. Users may need to pass these environmental variables into other applications if they do not natively take these variables
|
||||||
5. Action authors may need to update their workflows to react to these environment variables
|
5. Action authors may need to update their workflows to react to the these environment variables
|
||||||
6. We will document the way of setting environment variables for runners using the environment variables and how the runner uses them
|
6. We will document the way of setting environmental variables for runners using the environmental variables and how the runner uses them
|
||||||
7. Like all other secrets, users will be able to relatively easily figure out the proxy password if they can modify a workflow file running on a self-hosted machine
|
7. Like all other secrets, users will be able to relatively easily figure out proxy password if they can modify a workflow file running on a self hosted machine
|
||||||
@@ -10,7 +10,7 @@ Compilation failures during a CI build should surface good error messages.
|
|||||||
|
|
||||||
For example, the actual compile errors from the typescript compiler should bubble as issues in the UI. And not simply "tsc exited with exit code 1".
|
For example, the actual compile errors from the typescript compiler should bubble as issues in the UI. And not simply "tsc exited with exit code 1".
|
||||||
|
|
||||||
VSCode has an extensible model for solving this type of problem. VSCode allows users to configure which [problems matchers](https://code.visualstudio.com/docs/editor/tasks#_defining-a-problem-matcher) to use, when scanning output. For example, a user can apply the `tsc` problem matcher to receive a rich error output experience in VSCode, when compiling their typescript project.
|
VSCode has an extensible model for solving this type of problem. VSCode allows users to configure which problems matchers to use, when scanning output. For example, a user can apply the `tsc` problem matcher to receive a rich error output experience in VSCode, when compiling their typescript project.
|
||||||
|
|
||||||
The problem-matcher concept fits well with "setup" actions. For example, the `setup-nodejs` action will download node.js, add it to the PATH, and register the `tsc` problem matcher. For the duration of the job, the `tsc` problem matcher will be applied against the output.
|
The problem-matcher concept fits well with "setup" actions. For example, the `setup-nodejs` action will download node.js, add it to the PATH, and register the `tsc` problem matcher. For the duration of the job, the `tsc` problem matcher will be applied against the output.
|
||||||
|
|
||||||
@@ -18,25 +18,23 @@ The problem-matcher concept fits well with "setup" actions. For example, the `se
|
|||||||
|
|
||||||
### Registration
|
### Registration
|
||||||
|
|
||||||
#### Using `::` command
|
#### Using `##` command
|
||||||
|
|
||||||
`::add-matcher::path-to-problem-matcher-config.json`
|
`##[add-matcher]path-to-problem-matcher-config.json`
|
||||||
|
|
||||||
Using a `::` command allows for flexibility:
|
Using a `##` command allows for flexibility:
|
||||||
- Ad hoc scripts can register problem matchers
|
- Ad hoc scripts can register problem matchers
|
||||||
- Allows problem matchers to be conditionally registered
|
- Allows problem matchers to be conditionally registered
|
||||||
|
|
||||||
Note, if a matcher with the same name is registered a second time, it will clobber the first instance.
|
Note, if a matcher with the same name is registered a second time, it will clobber the first instance.
|
||||||
|
|
||||||
Note, at some point the syntax changed from `##` to `::`.
|
#### Unregister using `##` command
|
||||||
|
|
||||||
#### Unregister using `::` command
|
|
||||||
|
|
||||||
A way out for rare cases where scoping is a problem.
|
A way out for rare cases where scoping is a problem.
|
||||||
|
|
||||||
`::remove-matcher::owner`
|
`##[remove-matcher]owner`
|
||||||
|
|
||||||
For this to be usable, the `owner` needs to be discoverable. Therefore, debug print the owner on registration.
|
For the this to be usable, the `owner` needs to be discoverable. Therefore, debug print the owner on registration.
|
||||||
|
|
||||||
### Single line matcher
|
### Single line matcher
|
||||||
|
|
||||||
@@ -106,7 +104,7 @@ message: ; expected
|
|||||||
fromPath: C:\myrepo\myproject\ConsoleApp1\ClassLibrary1\ClassLibrary1.csproj
|
fromPath: C:\myrepo\myproject\ConsoleApp1\ClassLibrary1\ClassLibrary1.csproj
|
||||||
```
|
```
|
||||||
|
|
||||||
Additionally the line will appear red in the web UI (prefix with `::error`).
|
Additionally the line will appear red in the web UI (prefix with `##[error]`).
|
||||||
|
|
||||||
Note, an error does not imply task failure. Exit codes communicate failure.
|
Note, an error does not imply task failure. Exit codes communicate failure.
|
||||||
|
|
||||||
@@ -186,7 +184,7 @@ Solving this problem means:
|
|||||||
- Use the `github.workspace` (where the repo is cloned on disk)
|
- Use the `github.workspace` (where the repo is cloned on disk)
|
||||||
- Match against a repository to determine the relative path within the repo
|
- Match against a repository to determine the relative path within the repo
|
||||||
|
|
||||||
This is a place where we diverge from VSCode. VSCode task configurations are specific to the local workspace (workspace root is known or can be specified). We're solving a more generic problem, so we need more information - specifically the `fromPath` property - in order to accurately root the path.
|
This is a place where we diverge from VSCode. VSCode task configuration are specific to the local workspace (workspace root is known or can be specified). We're solving a more generic problem, so we need more information - specifically the `fromPath` property - in order to accurately root the path.
|
||||||
|
|
||||||
In order to avoid creating inaccurate hyperlinks on the error issues, the agent will verify the file exists and is in the main repository. Otherwise omit the file property from the error issue and debug trace what happened.
|
In order to avoid creating inaccurate hyperlinks on the error issues, the agent will verify the file exists and is in the main repository. Otherwise omit the file property from the error issue and debug trace what happened.
|
||||||
|
|
||||||
@@ -205,7 +203,7 @@ Problem matchers are unable to interpret severity strings other than `warning` a
|
|||||||
|
|
||||||
However some tools indicate error/warning in different ways. For example `flake8` uses codes like `E100`, `W200`, and `F300` (error, warning, fatal, respectively).
|
However some tools indicate error/warning in different ways. For example `flake8` uses codes like `E100`, `W200`, and `F300` (error, warning, fatal, respectively).
|
||||||
|
|
||||||
Therefore, allow a property `severity`, sibling to `owner`, which identifies the default severity for the problem matcher. This allows two problem matchers to be registered - one for warnings and one for errors.
|
Therefore, allow a property `severity`, sibling to `owner`, which identifies the default severity for the problem matcher. This allows two problem matchers are registered - one for warnings and one for errors.
|
||||||
|
|
||||||
For example, given the following `flake8` output:
|
For example, given the following `flake8` output:
|
||||||
|
|
||||||
@@ -250,42 +248,6 @@ Two problem matchers can be used:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Default from path
|
|
||||||
|
|
||||||
The problem matcher can specify a `fromPath` property at the top level, which applies when a specific pattern doesn't provide a value for `fromPath`. This is useful for tools that don't include project file information in their output.
|
|
||||||
|
|
||||||
For example, given the following compiler output that doesn't include project file information:
|
|
||||||
|
|
||||||
```
|
|
||||||
ClassLibrary.cs(16,24): warning CS0612: 'ClassLibrary.Helpers.MyHelper.Name' is obsolete
|
|
||||||
```
|
|
||||||
|
|
||||||
A problem matcher with a default from path can be used:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"problemMatcher": [
|
|
||||||
{
|
|
||||||
"owner": "csc-minimal",
|
|
||||||
"fromPath": "ClassLibrary/ClassLibrary.csproj",
|
|
||||||
"pattern": [
|
|
||||||
{
|
|
||||||
"regexp": "^(.+)\\((\\d+),(\\d+)\\): (error|warning) (.+): (.*)$",
|
|
||||||
"file": 1,
|
|
||||||
"line": 2,
|
|
||||||
"column": 3,
|
|
||||||
"severity": 4,
|
|
||||||
"code": 5,
|
|
||||||
"message": 6
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This ensures that the file is rooted to the correct path when there's not enough information in the error messages to extract a `fromPath`.
|
|
||||||
|
|
||||||
#### Mitigate regular expression denial of service (ReDos)
|
#### Mitigate regular expression denial of service (ReDos)
|
||||||
|
|
||||||
If a matcher exceeds a 1 second timeout when processing a line, retry up to two three times total.
|
If a matcher exceeds a 1 second timeout when processing a line, retry up to two three times total.
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
run-actions run scripts using a platform specific shell:
|
run-actions run scripts using a platform specific shell:
|
||||||
`bash -eo pipefail` on non-windows, and `cmd.exe /c /d /s` on windows
|
`bash -eo pipefail` on non-windows, and `cmd.exe /c /d /s` on windows
|
||||||
|
|
||||||
The `shell` option overrides this to allow different flags or completely different shells/interpreters
|
The `shell` option overwrites this to allow different flags or completely different shells/interpreters
|
||||||
|
|
||||||
A small example is:
|
A small example is:
|
||||||
```yml
|
```yml
|
||||||
@@ -84,7 +84,7 @@ powershell/pwsh
|
|||||||
- Users can always opt out by not using the builtins, and providing a shell option like: `pwsh -File {0}`, or `powershell -Command "& '{0}'"`, depending on need
|
- Users can always opt out by not using the builtins, and providing a shell option like: `pwsh -File {0}`, or `powershell -Command "& '{0}'"`, depending on need
|
||||||
|
|
||||||
cmd
|
cmd
|
||||||
- There doesn't seem to be a way to fully opt in to fail-fast behavior other than writing your script to check each error code and respond accordingly, so we can't actually provide that behavior by default, it will be completely up to the user to write this behavior into their script
|
- There doesnt seem to be a way to fully opt in to fail-fast behavior other than writing your script to check each error code and respond accordingly, so we cant actually provide that behavior by default, it will be completely up to the user to write this behavior into their script
|
||||||
- cmd.exe will exit (return the error code to the runner) with the errorlevel of the last program it executed. This is internally consistent with the previous default behavior (sh, pwsh) and is the cmd.exe default, so we keep that behavior
|
- cmd.exe will exit (return the error code to the runner) with the errorlevel of the last program it executed. This is internally consistent with the previous default behavior (sh, pwsh) and is the cmd.exe default, so we keep that behavior
|
||||||
|
|
||||||
## Consequences
|
## Consequences
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
**Status**: Accepted
|
**Status**: Accepted
|
||||||
|
|
||||||
## Context
|
## Context
|
||||||
First party action `actions/cache` needs a input which is an explicit `key` used for restoring and saving the cache. For packages caching, the most common `key` might be the hash result of contents from all `package-lock.json` under `node_modules` folder.
|
First party action `actions/cache` needs a input which is an explicit `key` used for restoring and saving the cache. For packages caching, the most comment `key` might be the hash result of contents from all `package-lock.json` under `node_modules` folder.
|
||||||
|
|
||||||
There are serval different ways to get the hash `key` input for `actions/cache` action.
|
There are serval different ways to get the hash `key` input for `actions/cache` action.
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ There are serval different ways to get the hash `key` input for `actions/cache`
|
|||||||
`hashFiles()` will only support hashing files under the `$GITHUB_WORKSPACE` since the expression evaluated on the runner, if customer use job container or container action, the runner won't have access to file system inside the container.
|
`hashFiles()` will only support hashing files under the `$GITHUB_WORKSPACE` since the expression evaluated on the runner, if customer use job container or container action, the runner won't have access to file system inside the container.
|
||||||
|
|
||||||
`hashFiles()` will only take 1 parameters:
|
`hashFiles()` will only take 1 parameters:
|
||||||
- `hashFiles('**/package-lock.json')` // Search files under `$GITHUB_WORKSPACE` and calculate a hash for them
|
- `hashFiles('**/package-lock.json')` // Search files under $GITHUB_WORKSPACE and calculate a hash for them
|
||||||
|
|
||||||
**Question: Do we need to support more than one match patterns?**
|
**Question: Do we need to support more than one match patterns?**
|
||||||
Ex: `hashFiles('**/package-lock.json', '!toolkit/core/package-lock.json', '!toolkit/io/package-lock.json')`
|
Ex: `hashFiles('**/package-lock.json', '!toolkit/core/package-lock.json', '!toolkit/io/package-lock.json')`
|
||||||
@@ -52,7 +52,7 @@ This will help customer has better experience with the `actions/cache` action's
|
|||||||
key: ${{hashFiles('**/package-lock.json')}}-${{github.ref}}-${{runner.os}}
|
key: ${{hashFiles('**/package-lock.json')}}-${{github.ref}}-${{runner.os}}
|
||||||
```
|
```
|
||||||
|
|
||||||
For search pattern, we will use basic globbing (`*`, `?`, and `[]`) and globstar (`**`).
|
For search pattern, we will use basic globbing (`*` `?` and `[]`) and globstar (`**`).
|
||||||
|
|
||||||
Additional pattern details:
|
Additional pattern details:
|
||||||
- Root relative paths with `github.workspace` (the main repo)
|
- Root relative paths with `github.workspace` (the main repo)
|
||||||
@@ -68,4 +68,4 @@ Hashing logic:
|
|||||||
5. Use SHA256 to hash all stored files' hash results to get the final 64 chars hash result.
|
5. Use SHA256 to hash all stored files' hash results to get the final 64 chars hash result.
|
||||||
|
|
||||||
**Question: Should we include the folder structure info into the hash?**
|
**Question: Should we include the folder structure info into the hash?**
|
||||||
Answer: No
|
Answer: No
|
||||||
@@ -15,7 +15,7 @@ This gives us good coverage across the board for secrets and secrets with a pref
|
|||||||
|
|
||||||
However, we don't have great coverage for cases where the secret has a string appended to it before it is base64 encoded (i.e.: `base64($pass\n))`).
|
However, we don't have great coverage for cases where the secret has a string appended to it before it is base64 encoded (i.e.: `base64($pass\n))`).
|
||||||
|
|
||||||
Most notably we've seen this as a result of user error where a user accidentally appends a newline or space character before encoding their secret in base64.
|
Most notably we've seen this as a result of user error where a user accidentially appends a newline or space character before encoding their secret in base64.
|
||||||
|
|
||||||
## Decision
|
## Decision
|
||||||
|
|
||||||
@@ -45,4 +45,4 @@ This will result in us only revealing length or bit information when a prefix or
|
|||||||
|
|
||||||
- In the case where a secret has a prefix or suffix added before base64 encoding, we may now reveal up to 20 bits of information and the length of the original string modulo 3, rather then the original 16 bits and no length information
|
- In the case where a secret has a prefix or suffix added before base64 encoding, we may now reveal up to 20 bits of information and the length of the original string modulo 3, rather then the original 16 bits and no length information
|
||||||
- Secrets with a suffix appended before encoding will now be masked across the board. Previously it was only masked if it was a multiple of 3 characters
|
- Secrets with a suffix appended before encoding will now be masked across the board. Previously it was only masked if it was a multiple of 3 characters
|
||||||
- Performance will suffer in a negligible way
|
- Performance will suffer in a neglible way
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ The runner will look for a file `.setup_info` under the runner's root directory,
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
The runner will use `::group` and `::endgroup` to fold all detail info into an expandable group.
|
The runner will use `##[group]` and `##[endgroup]` to fold all detail info into an expandable group.
|
||||||
|
|
||||||
Both [virtual-environments](https://github.com/actions/virtual-environments) and self-hosted runners can use this mechanism to add extra logging info to the `Set up job` step's log.
|
Both [virtual-environments](https://github.com/actions/virtual-environments) and self-hosted runners can use this mechanism to add extra logging info to the `Set up job` step's log.
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,10 @@
|
|||||||
|
|
||||||
## Context
|
## Context
|
||||||
|
|
||||||
In addition to action's regular execution, action author may wants their action to have a chance to participate in:
|
In addition to action's regular execution, action author may wants their action has a chance to participate in:
|
||||||
- Job initialization
|
- Job initialize
|
||||||
My Action will collect machine resource usage (CPU/RAM/Disk) during a workflow job execution, we need to start perf recorder at the beginning of the job.
|
My Action will collect machine resource usage (CPU/RAM/Disk) during a workflow job execution, we need to start perf recorder at the begin of the job.
|
||||||
- Job cleanup
|
- Job cleanup
|
||||||
My Action will dirty local workspace or machine environment during execution, we need to cleanup these changes at the end of the job.
|
My Action will dirty local workspace or machine environment during execution, we need to cleanup these changes at the end of the job.
|
||||||
Ex: `actions/checkout@v2` will write `github.token` into local `.git/config` during execution, it has post job cleanup defined to undo the changes.
|
Ex: `actions/checkout@v2` will write `github.token` into local `.git/config` during execution, it has post job cleanup defined to undo the changes.
|
||||||
|
|
||||||
@@ -46,12 +46,12 @@ Container Action Example:
|
|||||||
post-if: 'success()' // Optional
|
post-if: 'success()' // Optional
|
||||||
```
|
```
|
||||||
|
|
||||||
Both `pre` and `post` will have default `pre-if/post-if` set to `always()`.
|
Both `pre` and `post` will has default `pre-if/post-if` sets to `always()`.
|
||||||
Setting `pre` to `always()` will make sure no matter what condition evaluate result the `main` gets at runtime, the `pre` has always run already.
|
Setting `pre` to `always()` will make sure no matter what condition evaluate result the `main` gets at runtime, the `pre` has always run already.
|
||||||
`pre` executes in order of how the steps are defined.
|
`pre` executes in order of how the steps are defined.
|
||||||
`pre` will always be added to job steps list during job setup.
|
`pre` will always be added to job steps list during job setup.
|
||||||
> Action referenced from local repository (`./my-action`) won't get `pre` setup correctly since the repository haven't checked-out during job initialization.
|
> Action referenced from local repository (`./my-action`) won't get `pre` setup correctly since the repository haven't checkout during job initialize.
|
||||||
> We can't use GitHub api to download the repository since there is about a 3 minute delay between `git push` and the new commit available to download using GitHub api.
|
> We can't use GitHub api to download the repository since there is a about 3 mins delay between `git push` and the new commit available to download using GitHub api.
|
||||||
|
|
||||||
`post` will be pushed into a `poststeps` stack lazily when the action's `pre` or `main` execution passed `if` condition check and about to run, you can't have an action that only contains a `post`, we will pop and run each `post` after all `pre` and `main` finished.
|
`post` will be pushed into a `poststeps` stack lazily when the action's `pre` or `main` execution passed `if` condition check and about to run, you can't have an action that only contains a `post`, we will pop and run each `post` after all `pre` and `main` finished.
|
||||||
> Currently `post` works for both repository action (`org/repo@v1`) and local action (`./my-action`)
|
> Currently `post` works for both repository action (`org/repo@v1`) and local action (`./my-action`)
|
||||||
@@ -60,7 +60,7 @@ Valid action:
|
|||||||
- only has `main`
|
- only has `main`
|
||||||
- has `pre` and `main`
|
- has `pre` and `main`
|
||||||
- has `main` and `post`
|
- has `main` and `post`
|
||||||
- has `pre`, `main`, and `post`
|
- has `pre`, `main` and `post`
|
||||||
|
|
||||||
Invalid action:
|
Invalid action:
|
||||||
- only has `pre`
|
- only has `pre`
|
||||||
|
|||||||
@@ -13,13 +13,13 @@ This is another version of [ADR275](https://github.com/actions/runner/pull/275)
|
|||||||
|
|
||||||
## Decision
|
## Decision
|
||||||
|
|
||||||
This ADR proposes that we add a `--labels` option to the `config`, which could be used to add custom additional labels to the configured runner.
|
This ADR proposes that we add a `--labels` option to `config`, which could be used to add custom additional labels to the configured runner.
|
||||||
|
|
||||||
For example, to add a single additional label the operator could run:
|
For example, to add a single extra label the operator could run:
|
||||||
```bash
|
```bash
|
||||||
./config.sh --labels mylabel
|
./config.sh --labels mylabel
|
||||||
```
|
```
|
||||||
> Note: the current runner command line parsing and envvar override algorithm only support a single argument (key).
|
> Note: the current runner command line parsing and envvar override algorithm only supports a single argument (key).
|
||||||
|
|
||||||
This would add the label `mylabel` to the runner, and enable users to select the runner in their workflow using this label:
|
This would add the label `mylabel` to the runner, and enable users to select the runner in their workflow using this label:
|
||||||
```yaml
|
```yaml
|
||||||
@@ -39,17 +39,17 @@ runs-on: [self-hosted, mylabel, anotherlabel]
|
|||||||
|
|
||||||
It would not be possible to remove labels from an existing runner using `config.sh`, instead labels would have to be removed using the GitHub UI.
|
It would not be possible to remove labels from an existing runner using `config.sh`, instead labels would have to be removed using the GitHub UI.
|
||||||
|
|
||||||
The labels argument will split on commas, trim and discard empty strings. That effectively means don't use commas in unattended config label names. Alternatively, we could choose to escape commas but it's a nice to have.
|
The labels argument will split on commas, trim and discard empty strings. That effectively means don't use commans in unattended config label names. Alternatively we could choose to escape commans but it's a nice to have.
|
||||||
|
|
||||||
## Replace
|
## Replace
|
||||||
|
|
||||||
If an existing runner exists and the option to replace is chosen (interactively or via unattended as in this scenario), then the labels will be replaced/overwritten (not merged).
|
If an existing runner exists and the option to replace is chosen (interactively of via unattend as in this scenario), then the labels will be replaced / overwritten (not merged).
|
||||||
|
|
||||||
## Overriding built-in labels
|
## Overriding built-in labels
|
||||||
|
|
||||||
Note that it is possible to register "built-in" hosted labels like `ubuntu-latest` and is not considered an error. This is an effective way for the org/runner admin to dictate by policy through registration that this set of runners will be used without having to edit all the workflow files now and in the future.
|
Note that it is possible to register "built-in" hosted labels like `ubuntu-latest` and is not considered an error. This is an effective way for the org / runner admin to dictate by policy through registration that this set of runners will be used without having to edit all the workflow files now and in the future.
|
||||||
|
|
||||||
We will also not make other restrictions such as limiting explicitly adding os/arch labels and validating. We will assume that explicit labels were added for a reason and not restricting offers the most flexibility and future-proofing / compatibility.
|
We will also not make other restrictions such as limiting explicitly adding os / arch labels and validating. We will assume that explicit labels were added for a reason and not restricting offers the most flexibility and future proofing / compat.
|
||||||
|
|
||||||
## Consequences
|
## Consequences
|
||||||
|
|
||||||
|
|||||||
@@ -8,17 +8,17 @@
|
|||||||
|
|
||||||
Customers want to be able to compose actions from actions (ex: https://github.com/actions/runner/issues/438)
|
Customers want to be able to compose actions from actions (ex: https://github.com/actions/runner/issues/438)
|
||||||
|
|
||||||
An important step towards meeting this goal is to build functionality for actions where users can simply execute any number of steps.
|
An important step towards meeting this goal is to build in functionality for actions where users can simply execute any number of steps.
|
||||||
|
|
||||||
### Guiding Principles
|
### Guiding Principles
|
||||||
|
|
||||||
We don't want the workflow author to need to know how the internal workings of the action work. Users shouldn't know the internal workings of the composite action (for example, `default.shell` and `default.workingDir` should not be inherited from the workflow file to the action file). When deciding how to design certain parts of composite run steps, we want to treat it as one logical step for the consumer.
|
We don't want the workflow author to need to know how the internal workings of the action work. Users shouldn't know the internal workings of the composite action (for example, `default.shell` and `default.workingDir` should not be inherited from the workflow file to the action file). When deciding how to design certain parts of composite run steps, we want to think one logical step from the consumer.
|
||||||
|
|
||||||
A composite action is treated as **one** individual job step (this is known as encapsulation).
|
A composite action is treated as **one** individual job step (this is known as encapsulation).
|
||||||
|
|
||||||
## Decision
|
## Decision
|
||||||
|
|
||||||
**In this ADR, we only support running multiple run steps in an Action.** In doing so, we build in support for mapping and flowing the inputs, outputs, and env variables (ex: All nested steps should have access to their parents' input variables and nested steps can overwrite the input variables).
|
**In this ADR, we only support running multiple run steps in an Action.** In doing so, we build in support for mapping and flowing the inputs, outputs, and env variables (ex: All nested steps should have access to its parents' input variables and nested steps can overwrite the input variables).
|
||||||
|
|
||||||
### Composite Run Steps Features
|
### Composite Run Steps Features
|
||||||
This feature supports at the top action level:
|
This feature supports at the top action level:
|
||||||
@@ -92,7 +92,7 @@ We will not support "defaults" in a composite action.
|
|||||||
|
|
||||||
### Shell and Working-directory
|
### Shell and Working-directory
|
||||||
|
|
||||||
For each run step in a composite action, the action author can set the `shell` and `working-directory` attributes for that step. The shell attribute is **required** for each run step because the action author does not know what the workflow author is using for the operating system so we need to explicitly prevent unknown behavior by making sure that each run step has an explicit shell **set by the action author.** On the other hand, `working-directory` is optional. Moreover, the composite action author can map in values from the `inputs` for its `shell` and `working-directory` attributes at the step level for an action.
|
For each run step in a composite action, the action author can set the `shell` and `working-directory` attributes for that step. The shell attribute is **required** for each run step because the action author does not know what the workflow author is using for the operating system so we need to explicitly prevent unknown behavior by making sure that each run step has an explicit shell **set by the action author.** On the other hand, `working-directory` is optional. Moreover, the composite action author can map in values from the `inputs` for it's `shell` and `working-directory` attributes at the step level for an action.
|
||||||
|
|
||||||
For example,
|
For example,
|
||||||
|
|
||||||
@@ -218,9 +218,9 @@ Example Output:
|
|||||||
random-number 43243
|
random-number 43243
|
||||||
```
|
```
|
||||||
|
|
||||||
Each of the output variables from the composite action is viewable from the workflow file that uses the composite action. In other words, every child's action output(s) are only viewable by its parent using dot notation (ex `steps.foo.outputs.random-number`).
|
Each of the output variables from the composite action is viewable from the workflow file that uses the composite action. In other words, every child action output(s) is viewable only by its parent using dot notation (ex `steps.foo.outputs.random-number`).
|
||||||
|
|
||||||
Moreover, the output ids are only accessible within the scope where it was defined. Note that in the example above, in our `workflow.yml` file, it should not have access to output id (i.e. `random-id`). The reason why we are doing this is that we don't want to require the workflow author to know the internal workings of the composite action.
|
Moreover, the output ids are only accessible within the scope where it was defined. Note that in the example above, in our `workflow.yml` file, it should not have access to output id (i.e. `random-id`). The reason why we are doing this is because we don't want to require the workflow author to know the internal workings of the composite action.
|
||||||
|
|
||||||
### Context
|
### Context
|
||||||
|
|
||||||
@@ -237,9 +237,9 @@ In the Composite Action, you'll only be able to use `::set-env::` to set environ
|
|||||||
We'll pass the secrets from the composite action's parents (ex: the workflow file) to the composite action. Secrets can be created in the composite action with the secrets context. In the actions yaml, we'll automatically mask the secret.
|
We'll pass the secrets from the composite action's parents (ex: the workflow file) to the composite action. Secrets can be created in the composite action with the secrets context. In the actions yaml, we'll automatically mask the secret.
|
||||||
|
|
||||||
|
|
||||||
### If-Condition
|
### If Condition
|
||||||
|
|
||||||
** `If` and `needs` conditions will not be supported in the composite run steps feature. It will be supported later on in a new feature. **
|
** If and needs conditions will not be supported in the composite run steps feature. It will be supported later on in a new feature. **
|
||||||
|
|
||||||
Old reasoning:
|
Old reasoning:
|
||||||
|
|
||||||
@@ -248,7 +248,7 @@ Example `workflow.yml`:
|
|||||||
```yaml
|
```yaml
|
||||||
steps:
|
steps:
|
||||||
- run: exit 1
|
- run: exit 1
|
||||||
- uses: user/composite@v1 # <--- this will run, as it's marked as always running
|
- uses: user/composite@v1 # <--- this will run, as it's marked as always runing
|
||||||
if: always()
|
if: always()
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -269,15 +269,15 @@ runs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
```
|
```
|
||||||
|
|
||||||
**We will not support "if-condition" in a composite action for now. This functionality will be focused on in a future ADR.**
|
**We will not support "if Condition" in a composite action for now. This functionality will be focused on in a future ADR.**
|
||||||
|
|
||||||
See the paragraph below for a rudimentary approach (thank you to @cybojenix for the idea, example, and explanation for this approach):
|
See the paragraph below for a rudimentary approach (thank you to @cybojenix for the idea, example, and explanation for this approach):
|
||||||
|
|
||||||
The `if` statement in the parent (in the example above, this is the `workflow.yml`) shows whether or not we should run the composite action. So, our composite action will run since the `if` condition for running the composite action is `always()`.
|
The `if` statement in the parent (in the example above, this is the `workflow.yml`) shows whether or not we should run the composite action. So, our composite action will run since the `if` condition for running the composite action is `always()`.
|
||||||
|
|
||||||
**Note that the "if-condition" on the parent does not propagate to the rest of its children though.**
|
**Note that the if condition on the parent does not propagate to the rest of its children though.**
|
||||||
|
|
||||||
In the child action (in this example, this is the `action.yml`), it starts with a clean slate (in other words, no imposing if-conditions). Similar to the logic in the paragraph above, `echo "I will run, as my current scope is succeeding"` will run since the `if` condition checks if the previous steps **within this composite action** have not failed. `run: echo "I will not run, as my current scope is now failing"` will not run since the previous step resulted in an error and by default, the if expression is set to `success()` if the if-condition is not set for a step.
|
In the child action (in this example, this is the `action.yml`), it starts with a clean slate (in other words, no imposing if conditions). Similar to the logic in the paragraph above, `echo "I will run, as my current scope is succeeding"` will run since the `if` condition checks if the previous steps **within this composite action** has not failed. `run: echo "I will not run, as my current scope is now failing"` will not run since the previous step resulted in an error and by default, the if expression is set to `success()` if the if condition is not set for a step.
|
||||||
|
|
||||||
|
|
||||||
What if a step has `cancelled()`? We do the opposite of our approach above if `cancelled()` is used for any of our composite run steps. We will cancel any step that has this condition if the workflow is cancelled at all.
|
What if a step has `cancelled()`? We do the opposite of our approach above if `cancelled()` is used for any of our composite run steps. We will cancel any step that has this condition if the workflow is cancelled at all.
|
||||||
@@ -314,13 +314,13 @@ runs:
|
|||||||
|
|
||||||
**We will not support "timeout-minutes" in a composite action for now. This functionality will be focused on in a future ADR.**
|
**We will not support "timeout-minutes" in a composite action for now. This functionality will be focused on in a future ADR.**
|
||||||
|
|
||||||
A composite action in its entirety is a job. You can set both timeout-minutes for the whole composite action or its steps as long as the sum of the `timeout-minutes` for each composite action step that has the attribute `timeout-minutes` is less than or equals to `timeout-minutes` for the composite action. There is no default timeout-minutes for each composite action step.
|
A composite action in its entirety is a job. You can set both timeout-minutes for the whole composite action or its steps as long as the the sum of the `timeout-minutes` for each composite action step that has the attribute `timeout-minutes` is less than or equals to `timeout-minutes` for the composite action. There is no default timeout-minutes for each composite action step.
|
||||||
|
|
||||||
If the time taken for any of the steps in combination or individually exceeds the whole composite action `timeout-minutes` attribute, the whole job will fail (1). If an individual step exceeds its own `timeout-minutes` attribute but the total time that has been used including this step is below the overall composite action `timeout-minutes`, the individual step will fail but the rest of the steps will run based on their own `timeout-minutes` attribute (they will still abide by condition (1) though).
|
If the time taken for any of the steps in combination or individually exceed the whole composite action `timeout-minutes` attribute, the whole job will fail (1). If an individual step exceeds its own `timeout-minutes` attribute but the total time that has been used including this step is below the overall composite action `timeout-minutes`, the individual step will fail but the rest of the steps will run based on their own `timeout-minutes` attribute (they will still abide by condition (1) though).
|
||||||
|
|
||||||
For reference, in the example above, if the composite step `foo1` takes 11 minutes to run, that step will fail but the rest of the steps, `foo1` and `foo2`, will proceed as long as their total runtime with the previous failed `foo1` action is less than the composite action's `timeout-minutes` (50 minutes). If the composite step `foo2` takes 51 minutes to run, it will cause the whole composite action job to fail.
|
For reference, in the example above, if the composite step `foo1` takes 11 minutes to run, that step will fail but the rest of the steps, `foo1` and `foo2`, will proceed as long as their total runtime with the previous failed `foo1` action is less than the composite action's `timeout-minutes` (50 minutes). If the composite step `foo2` takes 51 minutes to run, it will cause the whole composite action job to fail. I
|
||||||
|
|
||||||
The rationale behind this is that users can configure their steps with the `if` condition to conditionally set how steps rely on each other. Due to the additional capabilities that are offered with combining `timeout-minutes` and/or `if`, we wanted the `timeout-minutes` condition to be as dumb as possible and not affect other steps.
|
The rationale behind this is that users can configure their steps with the `if` condition to conditionally set how steps rely on each other. Due to the additional capabilities that are offered with combining `timeout-minutes` and/or `if`, we wanted the `timeout-minutes` condition to be as dumb as possible and not effect other steps.
|
||||||
|
|
||||||
[Usage limits still apply](https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions?query=if%28%29#usage-limits)
|
[Usage limits still apply](https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions?query=if%28%29#usage-limits)
|
||||||
|
|
||||||
@@ -361,7 +361,7 @@ For the composite action steps, it follows the same logic as above. In this exam
|
|||||||
### Visualizing Composite Action in the GitHub Actions UI
|
### Visualizing Composite Action in the GitHub Actions UI
|
||||||
We want all the composite action's steps to be condensed into the original composite action node.
|
We want all the composite action's steps to be condensed into the original composite action node.
|
||||||
|
|
||||||
Here is a visual representation of the [first example](#Steps)
|
Here is a visual represenation of the [first example](#Steps)
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
| composite_action_node |
|
| composite_action_node |
|
||||||
|
|||||||
@@ -1,92 +0,0 @@
|
|||||||
**Date**: 2021-06-10
|
|
||||||
|
|
||||||
**Status**: Accepted
|
|
||||||
|
|
||||||
## Context
|
|
||||||
|
|
||||||
We released [composite run steps](https://github.com/actions/runner/pull/554) last year which started our journey of reusing steps across different workflow files. To continue that journey, we want to expand composite run steps into composite actions.
|
|
||||||
|
|
||||||
We want to support the `uses` steps from workflows in composite actions, including:
|
|
||||||
- Container actions
|
|
||||||
- Javascript actions
|
|
||||||
- Other Composite actions (up to a limit of course!)
|
|
||||||
- The pre and post steps these actions can generate
|
|
||||||
|
|
||||||
## Guiding Principles
|
|
||||||
|
|
||||||
- Composite Actions should function as a single step or action, no matter how many steps it is composed of or how many levels of recursion it has
|
|
||||||
- In the future we may add a configurable option to make this no longer the case
|
|
||||||
- A workflow author should not need to understand the inner workings of a composite action in order to use it
|
|
||||||
- Composite actions should leverage inputs to get values they need, they will not have full access to the `context` objects. The secrets context will **not** be available to composite actions, users will need to pass these values in as an input.
|
|
||||||
- Other Actions should **just work** inside a composite action, without any code changes
|
|
||||||
|
|
||||||
## Decisions
|
|
||||||
|
|
||||||
### Composite Recursion Limit
|
|
||||||
|
|
||||||
- We will start with supporting a recursion limit of `10` composite actions deep
|
|
||||||
- We are free to bump this limit in the future, the code will be written to just require updating a variable. If the graph evaluates beyond the recursion limit, the job will fail in the pre-job phase (The `Set up job` step).
|
|
||||||
- A composite actions interface is its inputs and outputs, nothing else is carried over when invoking recursively.
|
|
||||||
|
|
||||||
### Pre/Post Steps in nested Actions
|
|
||||||
|
|
||||||
- We do not plan on adding the ability to configure a customizable pre or post step for composite actions at this time. However, we will execute the pre and post steps of any actions referenced in a composite action.
|
|
||||||
- Composite actions will generate a single pre-step and post-step for the entire composite action, even if there are multiple pre-steps and post-steps in the referenced actions.
|
|
||||||
- These steps will execute following the same ordering rules we have today, first to run has their pre step run first and their post step run last.
|
|
||||||
- For example, if you had a composite action with two pre steps and two posts steps:
|
|
||||||
|
|
||||||
```
|
|
||||||
- uses: action1
|
|
||||||
- uses: composite1
|
|
||||||
- uses: action2
|
|
||||||
```
|
|
||||||
|
|
||||||
The order of execution would be:
|
|
||||||
|
|
||||||
```
|
|
||||||
- prestep-action1
|
|
||||||
- prestep-composite1
|
|
||||||
- prestep-composite1-first-action-referenced
|
|
||||||
- prestep-composite1-second-action-referenced
|
|
||||||
- prestep-action2
|
|
||||||
- the job steps
|
|
||||||
- poststep-action2
|
|
||||||
- poststep-composite1
|
|
||||||
- poststep-composite1-the-second-action-referenced
|
|
||||||
- poststep-composite1-first-action-referenced
|
|
||||||
- poststep-action1
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Set-state
|
|
||||||
|
|
||||||
- While the composite action has an individual combined pre/post action, the `set-state` command will not be shared.
|
|
||||||
- If the `set-state` command is used during a composite step, only the action that originally called `set-state` will have access to the env variable during the post run step.
|
|
||||||
- This prevents multiple actions that set the same state from interfering with the execution of another action's post step.
|
|
||||||
|
|
||||||
### Resolve Action Endpoint changes
|
|
||||||
|
|
||||||
- The resolve actions endpoint will now validate policy to ensure that the given workflow run has access to download that action.
|
|
||||||
- Older GHES/GHAE customers with newer runners will be locked out of composite uses steps until they upgrade their instance.
|
|
||||||
|
|
||||||
### Local actions
|
|
||||||
- Local actions will expand the tree, perform policy checks, and download actions Just in Time when the step is running.
|
|
||||||
- Like current local actions, we will not support presteps. If an action is running local, by the time we know that, the time to run presteps have already passed.
|
|
||||||
|
|
||||||
### If, continue-on-error, timeout-minutes - Not being considered at this time
|
|
||||||
|
|
||||||
- `if`, `continue-on-error`, `timeout-minutes` could be supported in composite run/uses steps. These values were not originally supported in our composite run steps implementation.
|
|
||||||
- Browsing the community forums and runner repo, there hasn't been a lot of noise asking for these features, so we will hold off on them.
|
|
||||||
- These values passed as input into the composite action will **not** be carried over as input into the individual steps the composite action runs.
|
|
||||||
|
|
||||||
### Defaults - Not being considered at this time
|
|
||||||
|
|
||||||
- In actions, we have the idea of [defaults](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#defaultsrun) , which allow you to specify a shell and working directory in one location, rather then on each step.
|
|
||||||
- However, `shell` is currently required in composite run steps
|
|
||||||
- In regular run steps, it is optional, and defaults to a different value based on the OS.
|
|
||||||
- We want to prioritize the right experience for the consumer, and make the action author continue to explicitly set these values. We can consider improving this experience in the future.
|
|
||||||
|
|
||||||
## Consequences
|
|
||||||
|
|
||||||
- Workflows are now more reusable across multiple workflow files
|
|
||||||
- Composite actions implement most of the existing workflow run steps, with room to expand these in the future
|
|
||||||
- Feature flags will control this rollout
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
# ADR 1438: Support Conditionals In Composite Actions
|
|
||||||
|
|
||||||
**Date**: 2021-10-13
|
|
||||||
|
|
||||||
**Status**: Accepted
|
|
||||||
|
|
||||||
## Context
|
|
||||||
|
|
||||||
We recently shipped composite actions, which allows you to reuse individual steps inside an action.
|
|
||||||
However, one of the [most requested features](https://github.com/actions/runner/issues/834) has been a way to support the `if` keyword.
|
|
||||||
|
|
||||||
### Goals
|
|
||||||
- We want to keep consistent with current behavior
|
|
||||||
- We want to support conditionals via the `if` keyword
|
|
||||||
- Our built in functions like `success` should be implementable without calling them, for example you can do `job.status == success` rather then `success()` currently.
|
|
||||||
|
|
||||||
### How does composite currently work?
|
|
||||||
|
|
||||||
Currently, we have limited conditional support in composite actions for `pre` and `post` steps.
|
|
||||||
These are based on the `job status`, and support keywords like `always()`, `failed()`, `success()` and `cancelled()`.
|
|
||||||
However, generic or main steps do **not** support conditionals.
|
|
||||||
|
|
||||||
By default, in a regular workflow, a step runs on the `success()` condition. Which looks at the **job** **status**, sees if it is successful and runs.
|
|
||||||
|
|
||||||
By default, in a composite action, main steps run until a single step fails in that composite action, then the composite action is halted early. It does **not** care about the job status.
|
|
||||||
Pre, and post steps in composite actions use the job status to determine if they should run.
|
|
||||||
|
|
||||||
### How do we go forward?
|
|
||||||
|
|
||||||
Well, if we think about what composite actions are currently doing when invoking main steps, they are checking if the current composite action is successful.
|
|
||||||
Lets formalize that concept into a "real" idea.
|
|
||||||
|
|
||||||
- We will add an `action_status` field to the github context to mimic the [job's context status](https://docs.github.com/en/actions/learn-github-actions/contexts#job-context).
|
|
||||||
- We have an existing concept that does this `action_path` which is only set for composite actions on the github context.
|
|
||||||
- In a composite action during a main step, the `success()` function will check if `action_status == success`, rather then `job_status == success`. Failure will work the same way.
|
|
||||||
- Pre and post steps in composite actions will not change, they will continue to check the job status.
|
|
||||||
|
|
||||||
|
|
||||||
### Nested Scenario
|
|
||||||
For nested composite actions, we will follow the existing behavior, you only care about your current composite action, not any parents.
|
|
||||||
For example, lets imagine a scenario with a simple nested composite action
|
|
||||||
|
|
||||||
```
|
|
||||||
- Job
|
|
||||||
- Regular Step
|
|
||||||
- Composite Action
|
|
||||||
- runs: exit 1
|
|
||||||
- if: always()
|
|
||||||
uses: A child composite action
|
|
||||||
- if: success()
|
|
||||||
runs: echo "this should print"
|
|
||||||
- runs: echo "this should also print"
|
|
||||||
- if: success()
|
|
||||||
runs: echo "this will not print as the current composite action has failed already"
|
|
||||||
|
|
||||||
```
|
|
||||||
The child composite actions steps should run in this example, the child composite action has not yet failed, so it should run all steps until a step fails. This is consistent with how a composite action currently works in production if the main job fails but a composite action is invoked with `if:always()` or `if: failure()`
|
|
||||||
|
|
||||||
### Other options explored
|
|
||||||
We could add the `current_step_status` to the job context rather then `__status` to the steps context, however this comes with two major downsides:
|
|
||||||
- We need to support the field for every type of step, because its non trivial to remove a field from the job context once it has been added (its readonly)
|
|
||||||
- For all actions besides composite it would only every be `success`
|
|
||||||
- Its weird to have a `current_step` value on the job context
|
|
||||||
- We also explored a `__status` on the steps context.
|
|
||||||
- The `__` is required to prevent us from colliding with a step with id: status
|
|
||||||
- This felt wrong because the naming was not smooth, and did not fit into current conventions.
|
|
||||||
|
|
||||||
### Consequences
|
|
||||||
- github context has a new field for the status of the current composite action.
|
|
||||||
- We support conditional's in composite actions
|
|
||||||
- We keep the existing behavior for all users, but allow them to expand that functionality.
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
# ADR: Notification Hooks for Runners
|
|
||||||
|
|
||||||
## Context
|
|
||||||
|
|
||||||
This ADR details the design changes for supporting custom configurable hooks for on various runner events. This has been a long requested user feature [here](https://github.com/actions/runner/issues/1543), [here](https://github.com/actions/runner/issues/699) and [here](https://github.com/actions/runner/issues/1116) for users to have more information on runner observability, and for the ability to run cleanup and teardown jobs.
|
|
||||||
|
|
||||||
This feature is mainly intended for self hosted runner administrators.
|
|
||||||
|
|
||||||
**What we hope to solve with this feature**
|
|
||||||
1. A runner admininstrator is able to add custom scripts to cleanup their runner environment at the start or end of a job
|
|
||||||
2. A runner admininstrator is able to add custom scripts to help setup their runner environment at the beginning of a job, for reasons like [caching](https://github.com/actions/runner/issues/1543#issuecomment-1050346279)
|
|
||||||
3. A runner administrator is able to grab custom telemetry of jobs running on their self hosted runner
|
|
||||||
|
|
||||||
**What we don't think this will solve**
|
|
||||||
- Policy features that require certain steps run at the beginning or end of all jobs
|
|
||||||
- This would be better solved to in a central place in settings, rather then decentralized on each runner.
|
|
||||||
- The Proposed `Notification Hooks for Runners` is limited to self hosted runners, we don't beileve Policy features should be
|
|
||||||
- Reuse scenarios between jobs are covered by [composite actions](https://docs.github.com/en/actions/creating-actions/creating-a-composite-action) and [resuable workflows](https://docs.github.com/en/actions/using-workflows/reusing-workflows)
|
|
||||||
- Security applications, security should be handled on the policy side on the server, not decentralized on each runner
|
|
||||||
|
|
||||||
## Hooks
|
|
||||||
- We will expose 2 variables that users can set to enable hooks
|
|
||||||
- `ACTIONS_RUNNER_HOOK_JOB_STARTED`
|
|
||||||
- `ACTIONS_RUNNER_HOOK_JOB_COMPLETED`
|
|
||||||
|
|
||||||
You can set these variables to the **absolute** path of a `.sh` or `.ps1` file.
|
|
||||||
|
|
||||||
We will execute `pwsh` (fallback to `powershell`) or `bash` (fallback to `sh`) as appropriate.
|
|
||||||
- `.sh` files will execute with the args `-e {pathtofile}`
|
|
||||||
- `.ps1` files will execute with the args `-command \". '{pathtofile}'\"`
|
|
||||||
|
|
||||||
We will **not** set the [standard flags we typically set](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsshell) for `runs` commands. So, if you want to set `pipefail` on `bash` for example, you will need to do that in your script.
|
|
||||||
|
|
||||||
### UI
|
|
||||||
We want to ensure the experience for users invoking workflows is good, if hooks take too long, you may feel your job is delayed or broken. So, much like `Set Up Job`, we will generate two new steps automatically in your job, one for each configured hook:
|
|
||||||
- `Set up runner`
|
|
||||||
- `Complete runner`
|
|
||||||
|
|
||||||
These steps will contain all of the output from invoking your hook, so you will have visibility into the runtime. We will also provide information on the path to the hook, and what shell we are invoking it as, much like we do for `run: ` steps.
|
|
||||||
|
|
||||||
### Contexts
|
|
||||||
When running your hooks, some context on your job may be helpful.
|
|
||||||
- The scripts will have access to the standard [default environment variables](https://docs.github.com/en/actions/learn-github-actions/environment-variables#default-environment-variables)
|
|
||||||
- Some of these variables are step specific like `GITHUB_ACTION`, in which case they will not be set
|
|
||||||
- You can pull the full webhook event payload from `GITHUB_EVENT_PATH`
|
|
||||||
|
|
||||||
### Commands
|
|
||||||
Should we expose [Commands](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions) and [Environment Files](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#environment-files)
|
|
||||||
|
|
||||||
**Yes**. Imagine a scenario where a runner administrator is deprecating a runner pool, and they need to [warn users](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-a-warning-message) to swap to a different pool, we should support them in doing this. However, there are some limitations:
|
|
||||||
- [save-state](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#sending-values-to-the-pre-and-post-actions) will **not** be supported, these are not traditional steps with pre and post actions
|
|
||||||
- [set-output](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#using-workflow-commands-to-access-toolkit-functions) will **not** be supported, there is no `id` as this is not a traditional step
|
|
||||||
|
|
||||||
|
|
||||||
### Environment Files
|
|
||||||
We will also enable [Environment Files](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#environment-files) to support setup scenarios for the runner environment.
|
|
||||||
|
|
||||||
While a self hosted runner admin can [set env variables](https://docs.github.com/en/actions/hosting-your-own-runners/using-a-proxy-server-with-self-hosted-runners#using-a-env-file-to-set-the-proxy-configuration), these apply to all jobs. By enabling the ability to `add a path` and `set an env` we give runner admins the ability to do this dynamically based on the [workflows environment variables](https://docs.github.com/en/actions/learn-github-actions/environment-variables#default-environment-variables) to empower setup scenarios.
|
|
||||||
|
|
||||||
|
|
||||||
### Exit codes
|
|
||||||
These are **synchronous** hooks, so they will block job execution while they are being run. Exit code 0 will indicate a successful run of the hook and we will proceed with the job, any other exit code will fail the job with an appropriate annotation.
|
|
||||||
- There will be no support for `continue-on-error`
|
|
||||||
|
|
||||||
## Key Decisions
|
|
||||||
- We will expose 2 variables that users can set to enable hooks
|
|
||||||
- `ACTIONS_RUNNER_HOOK_JOB_STARTED`
|
|
||||||
- `ACTIONS_RUNNER_HOOK_JOB_COMPLETED`
|
|
||||||
- Users can set these variables to the path of a `.sh` or `.ps1` file, which we will execute when Jobs are started or completed.
|
|
||||||
- Output from these will be added to a new step at the start/end of a job named `Set up runner` or `Complete runner`.
|
|
||||||
- These steps will only be generated on runs with these hooks
|
|
||||||
- These hooks `always()` execute if the env variable is set
|
|
||||||
- These files will execute as the Runner user, outside of any container specification on the job
|
|
||||||
- These are **synchronous** hooks
|
|
||||||
- Runner admins can execute a background process for async hooks if they want
|
|
||||||
- We will fail the job and halt execution on any exit code that is not 0. The Runner admin is responsible for returning the correct exit code and ensuring resilency.
|
|
||||||
- This includes that the runner user needs access to the file in the env and the file must exist
|
|
||||||
- There will be no `continue-on-error` type option on launch
|
|
||||||
- There will be no `timeout` option on launch
|
|
||||||
|
|
||||||
## Consequences
|
|
||||||
- Runner admins have the ability to tie into the runner job execution to publish their own telemetry or perform their own cleanup or setup
|
|
||||||
- New steps will be added to the UI showcasing the output of these hooks
|
|
||||||
@@ -1,596 +0,0 @@
|
|||||||
# ADR 0000: Container Hooks
|
|
||||||
|
|
||||||
**Date**: 2022-05-12
|
|
||||||
|
|
||||||
**Status**: Accepted
|
|
||||||
|
|
||||||
# Background
|
|
||||||
|
|
||||||
[Job Hooks](https://github.com/actions/runner/blob/main/docs/adrs/1751-runner-job-hooks.md) have given users the ability to customize how their self hosted runners run a job.
|
|
||||||
Users also want the ability to customize how they run containers during the scope of the job, rather then being locked into the docker implementation we have in the runner. They may want to use podman, kubernetes, or even change the docker commands we run.
|
|
||||||
We should give them that option, and publish examples how how they can create their own hooks.
|
|
||||||
|
|
||||||
# Guiding Principles
|
|
||||||
- **Extensibility** is the focus, we need to make sure we are flexible enough to cover current and future scenarios, even at the cost of making it harder to utilize these hooks
|
|
||||||
- Args should map **directly** to yaml values provided by the user.
|
|
||||||
- For example, the current runner overrides `HOME`, we can do that in the hook, but we shouldn't pass that hook as an ENV with the other env's the user has set, as that is not user input, it is how the runner invokes containers
|
|
||||||
|
|
||||||
## Interface
|
|
||||||
- You will set the variable `ACTIONS_RUNNER_CONTAINER_HOOKS=/Users/foo/runner/hooks.js` which is the entrypoint to your hook handler.
|
|
||||||
- There is no partial opt in, you must handle every hook
|
|
||||||
- We will pass a command and some args via `stdin`
|
|
||||||
- An exit code of 0 is a success, every other exit code is a failure
|
|
||||||
- We will support the same runner commands we support in [Job Hooks](https://github.com/actions/runner/blob/main/docs/adrs/1751-runner-job-hooks.md)
|
|
||||||
- On timeout, we will send a sigint to your process. If you fail to terminate within a reasonable amount of time, we will send a sigkill, and eventually kill the process tree.
|
|
||||||
|
|
||||||
An example input looks like
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"command": "job_cleanup",
|
|
||||||
"responseFile": "/users/thboop/runner/_work/{guid}.json",
|
|
||||||
"args": {},
|
|
||||||
"state":
|
|
||||||
{
|
|
||||||
"id": "82e8219701fe096a35941d869cf8d71af1d943b5d3bdd718850fb87ac3042480"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
`command` is the command we expect you to invoke
|
|
||||||
`responseFile` is the file you need to write your output to, if the command has output
|
|
||||||
`args` are the specific arguments the command needs
|
|
||||||
`state` is a json blog you can pass around to maintain your state, this is covered in more details below.
|
|
||||||
|
|
||||||
### Writing responses to a file
|
|
||||||
All text written to stdout or stderr should appear in the job or step logs. With that in mind, we support a few ways to actually return data:
|
|
||||||
1. Wrapping the json in some unique tag and processing it like we do commands
|
|
||||||
2. Writing to a file
|
|
||||||
|
|
||||||
For 1, users typically view logging information as a safe action, so we worry someone accidentialy logging unsantized information and causing unexpected or un-secure behavior. We eventually plan to move off of stdout/stderr style commands in favor of a runner cli.
|
|
||||||
Investing in this area doesn't make a lot of sense at this time.
|
|
||||||
|
|
||||||
While writing to a file to communicate isn't the most ideal pattern, its an existing pattern in the runner and serves us well, so lets reuse it.
|
|
||||||
|
|
||||||
### Output
|
|
||||||
Your output must be correctly formatted json. An example output looks like:
|
|
||||||
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"state": {},
|
|
||||||
"context"
|
|
||||||
{
|
|
||||||
"container" :
|
|
||||||
{
|
|
||||||
"id": "82e8219701fe096a35941d869cf8d71af1d943b5d3bdd718850fb87ac3042480"
|
|
||||||
"network": "github_network_53269bd575974817b43f4733536b200c"
|
|
||||||
}
|
|
||||||
"services": {
|
|
||||||
"redis": {
|
|
||||||
"id": "60972d9aa486605e66b0dad4abb638dc3d9116f566579e418166eedb8abb9105",
|
|
||||||
"ports": {
|
|
||||||
"8080": "8080"
|
|
||||||
},
|
|
||||||
"network": "github_network_53269bd575974817b43f4733536b200c"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"alpine: true,
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
`state` is a unique field any command can return. If it is not empty, we will store the state for you and pass it into all future commands. You can overwrite it by having the next hook invoked return a unique state.
|
|
||||||
|
|
||||||
Other fields are dependent upon the command being run.
|
|
||||||
|
|
||||||
### Versioning
|
|
||||||
We will not version these hooks at launch. If needed, we can always major version split these hooks in the future. We will ship in Beta to allow for breaking changes for a few months.
|
|
||||||
|
|
||||||
### The Job Context
|
|
||||||
The [job context](https://docs.github.com/en/actions/learn-github-actions/contexts#example-contents-of-the-job-context) currently has a variety of fields that correspond to containers. We should consider allowing hooks to populate new fields in the job context. That is out of scope for this original release however.
|
|
||||||
|
|
||||||
## Hooks
|
|
||||||
Hooks are to be implemented at a very high level, and map to actions the runner does, rather then specific docker actions like `docker build` or `docker create`. By mapping to runner actions, we create a very extensible framework that is flexible enough to solve any user concerns in the future. By providing first party implementations, we give users easy starting points to customize specific hooks (like `docker build`) without having to write full blown solutions.
|
|
||||||
|
|
||||||
The other would be to provide hooks that mirror every docker call we make, and expose more hooks to help support k8s users, with the expectation that users may have to no-op on multiple hooks if they don't correspond to our use case.
|
|
||||||
|
|
||||||
Why we don't want to go that way
|
|
||||||
- It feels clunky, users need to understand which hooks they need to implement and which they can ignore, which isn't a great UX
|
|
||||||
- It doesn't scale well, I don't want to build a solution where we may need to add more hooks, by mapping to runner actions, updating hooks is a painful experience for users
|
|
||||||
- Its overwhelming, its easier to tell users to build 4 hooks and track data themselves, rather then 16 hooks where the runner needs certain information and then needs to provide that information back into each hook. If we expose `Container Create`, you need to return the container you created, then we do `container run` which uses that container. If we just give you an image and say create and run this container, you don't need to store the container id in the runner, and it maps better to k8s scenarios where we don't really have container ids.
|
|
||||||
|
|
||||||
### Prepare_job hook
|
|
||||||
The `prepare_job` hook is called when a job is started. We pass in any job or service containers the job has. We expect that you:
|
|
||||||
- Prune anything from previous jobs if needed
|
|
||||||
- Create a network if needed
|
|
||||||
- Pull the job and service containers
|
|
||||||
- Start the job container
|
|
||||||
- Start the service containers
|
|
||||||
- Write to the response file some information we need
|
|
||||||
- Required: if the container is alpine, otherwise x64
|
|
||||||
- Optional: any context fields you want to set on the job context, otherwise they will be unavailable for users to use
|
|
||||||
- Return 0 when the health checks have succeeded and the job/service containers are started
|
|
||||||
|
|
||||||
This hook will **always** be called if you have container hooks enabled, even if no service or job containers exist in the job. This allows you to fail the job or implement a default job container if you want to and no job container has been provided.
|
|
||||||
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Example Input</summary>
|
|
||||||
<br>
|
|
||||||
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"command": "prepare_job",
|
|
||||||
"responseFile": "/users/thboop/runner/_work/{guid}.json",
|
|
||||||
"state": {},
|
|
||||||
"args":
|
|
||||||
{
|
|
||||||
"jobContainer": {
|
|
||||||
"image": "node:14.16",
|
|
||||||
"workingDirectory": "/__w/thboop-test2/thboop-test2",
|
|
||||||
"createOptions": "--cpus 1",
|
|
||||||
"environmentVariables": {
|
|
||||||
"NODE_ENV": "development"
|
|
||||||
},
|
|
||||||
"userMountVolumes:[
|
|
||||||
{
|
|
||||||
"sourceVolumePath": "my_docker_volume",
|
|
||||||
"targetVolumePath": "/volume_mount",
|
|
||||||
"readOnly": false
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"mountVolumes": [
|
|
||||||
{
|
|
||||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work",
|
|
||||||
"targetVolumePath": "/__w",
|
|
||||||
"readOnly": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/externals",
|
|
||||||
"targetVolumePath": "/__e",
|
|
||||||
"readOnly": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_temp",
|
|
||||||
"targetVolumePath": "/__w/_temp",
|
|
||||||
"readOnly": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_actions",
|
|
||||||
"targetVolumePath": "/__w/_actions",
|
|
||||||
"readOnly": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_tool",
|
|
||||||
"targetVolumePath": "/__w/_tool",
|
|
||||||
"readOnly": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_temp/_github_home",
|
|
||||||
"targetVolumePath": "/github/home",
|
|
||||||
"readOnly": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_temp/_github_workflow",
|
|
||||||
"targetVolumePath": "/github/workflow",
|
|
||||||
"readOnly": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"registry": {
|
|
||||||
"username": "foo",
|
|
||||||
"password": "bar",
|
|
||||||
"serverUrl": "https://index.docker.io/v1"
|
|
||||||
},
|
|
||||||
"portMappings": [ "8080:80/tcp", "8080:80/udp" ]
|
|
||||||
},
|
|
||||||
"services": [
|
|
||||||
{
|
|
||||||
"contextName": "redis",
|
|
||||||
"image": "redis",
|
|
||||||
"createOptions": "--cpus 1",
|
|
||||||
"environmentVariables": {},
|
|
||||||
"mountVolumes": [],
|
|
||||||
"portMappings": [ "8080:80/tcp", "8080:80/udp" ]
|
|
||||||
"registry": {
|
|
||||||
"username": "foo",
|
|
||||||
"password": "bar",
|
|
||||||
"serverUrl": "https://index.docker.io/v1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Field Descriptions</summary>
|
|
||||||
<br>
|
|
||||||
|
|
||||||
```
|
|
||||||
Arg Fields:
|
|
||||||
|
|
||||||
jobContainer: **Optional** An Object containing information about the specified job container
|
|
||||||
"image": **Required** A string containing the docker image
|
|
||||||
"workingDirectory": **Required** A string containing the absolute path of the working directory
|
|
||||||
"createOptions": **Optional** The optional create options specified in the [YAML](https://docs.github.com/en/actions/using-jobs/running-jobs-in-a-container#example-running-a-job-within-a-container)
|
|
||||||
"environmentVariables": **Optional** A map of key value env's to set
|
|
||||||
"userMountVolumes: ** Optional** an array of user mount volumes set in the [YAML](https://docs.github.com/en/actions/using-jobs/running-jobs-in-a-container#example-running-a-job-within-a-container)
|
|
||||||
"sourceVolumePath": **Required** The source path to the volume to be mounted into the docker container
|
|
||||||
"targetVolumePath": **Required** The target path to the volume to be mounted into the docker container
|
|
||||||
"readOnly": false **Required** whether or not the mount should be read only
|
|
||||||
"mountVolumes": **Required** an array of mounts to mount into the container, same fields as above
|
|
||||||
"sourceVolumePath": **Required** The source path to the volume to be mounted into the docker container
|
|
||||||
"targetVolumePath": **Required** The target path to the volume to be mounted into the docker container
|
|
||||||
"readOnly": false **Required** whether or not the mount should be read only
|
|
||||||
"registry" **Optional** docker registry credentials to use when using a private container registry
|
|
||||||
"username": **Optional** the username
|
|
||||||
"password": **Optional** the password
|
|
||||||
"serverUrl": **Optional** the registry url
|
|
||||||
"portMappings": **Optional** an array of source:target ports to map into the container
|
|
||||||
|
|
||||||
"services": an array of service containers to spin up
|
|
||||||
"contextName": **Required** the name of the service in the Job context
|
|
||||||
"image": **Required** A string containing the docker image
|
|
||||||
"createOptions": **Optional** The optional create options specified in the [YAML](https://docs.github.com/en/actions/using-jobs/running-jobs-in-a-container#example-running-a-job-within-a-container)
|
|
||||||
"environmentVariables": **Optional** A map of key value env's to set
|
|
||||||
"mountVolumes": **Required** an array of mounts to mount into the container, same fields as above
|
|
||||||
"sourceVolumePath": **Required** The source path to the volume to be mounted into the docker container
|
|
||||||
"targetVolumePath": **Required** The target path to the volume to be mounted into the docker container
|
|
||||||
"readOnly": false **Required** whether or not the mount should be read only
|
|
||||||
"registry" **Optional** docker registry credentials to use when using a private container registry
|
|
||||||
"username": **Optional** the username
|
|
||||||
"password": **Optional** the password
|
|
||||||
"serverUrl": **Optional** the registry url
|
|
||||||
"portMappings": **Optional** an array of source:target ports to map into the container
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Example Output</summary>
|
|
||||||
<br>
|
|
||||||
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"state":
|
|
||||||
{
|
|
||||||
"network": "github_network_53269bd575974817b43f4733536b200c",
|
|
||||||
"jobContainer" : "82e8219701fe096a35941d869cf8d71af1d943b5d3bdd718850fb87ac3042480",
|
|
||||||
"serviceContainers":
|
|
||||||
{
|
|
||||||
"redis": "60972d9aa486605e66b0dad4abb638dc3d9116f566579e418166eedb8abb9105"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"context"
|
|
||||||
{
|
|
||||||
"container" :
|
|
||||||
{
|
|
||||||
"id": "82e8219701fe096a35941d869cf8d71af1d943b5d3bdd718850fb87ac3042480"
|
|
||||||
"network": "github_network_53269bd575974817b43f4733536b200c"
|
|
||||||
}
|
|
||||||
"services": {
|
|
||||||
"redis": {
|
|
||||||
"id": "60972d9aa486605e66b0dad4abb638dc3d9116f566579e418166eedb8abb9105",
|
|
||||||
"ports": {
|
|
||||||
"8080": "8080"
|
|
||||||
},
|
|
||||||
"network": "github_network_53269bd575974817b43f4733536b200c"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"alpine: true,
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
|
|
||||||
### Cleanup Job
|
|
||||||
The `cleanup_job` hook is called at the end of a job and expects you to:
|
|
||||||
- Stop any running service or job containers (or the equiavalent pod)
|
|
||||||
- Stop the network (if one exists)
|
|
||||||
- Delete any job or service containers (or the equiavalent pod)
|
|
||||||
- Delete the network (if one exists)
|
|
||||||
- Cleanup anything else that was created for the run
|
|
||||||
|
|
||||||
Its input looks like
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Example Input</summary>
|
|
||||||
<br>
|
|
||||||
|
|
||||||
```
|
|
||||||
"command": "cleanup_job",
|
|
||||||
"responseFile": null,
|
|
||||||
"state":
|
|
||||||
{
|
|
||||||
"network": "github_network_53269bd575974817b43f4733536b200c",
|
|
||||||
"jobContainer" : "82e8219701fe096a35941d869cf8d71af1d943b5d3bdd718850fb87ac3042480",
|
|
||||||
"serviceContainers":
|
|
||||||
{
|
|
||||||
"redis": "60972d9aa486605e66b0dad4abb638dc3d9116f566579e418166eedb8abb9105"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"args": {}
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
No args are provided.
|
|
||||||
|
|
||||||
No output is expected.
|
|
||||||
|
|
||||||
|
|
||||||
### Run Container Step
|
|
||||||
The `run_container_step` is called once per container action in your job and expects you to:
|
|
||||||
- Pull or build the required container (or fail if you cannot)
|
|
||||||
- Run the container action and return the exit code of the container
|
|
||||||
- Stream any step logs output to stdout and stderr
|
|
||||||
- Cleanup the container after it executes
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Example Input for Image</summary>
|
|
||||||
<br>
|
|
||||||
|
|
||||||
```
|
|
||||||
"command": "run_container_step",
|
|
||||||
"responseFile": null,
|
|
||||||
"state":
|
|
||||||
{
|
|
||||||
"network": "github_network_53269bd575974817b43f4733536b200c",
|
|
||||||
"jobContainer" : "82e8219701fe096a35941d869cf8d71af1d943b5d3bdd718850fb87ac3042480",
|
|
||||||
"serviceContainers":
|
|
||||||
{
|
|
||||||
"redis": "60972d9aa486605e66b0dad4abb638dc3d9116f566579e418166eedb8abb9105"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"args":
|
|
||||||
{
|
|
||||||
"image": "node:14.16",
|
|
||||||
"dockerfile": null,
|
|
||||||
"entryPointArgs": ["-f", "/dev/null"],
|
|
||||||
"entryPoint": "tail",
|
|
||||||
"workingDirectory": "/__w/thboop-test2/thboop-test2",
|
|
||||||
"createOptions": "--cpus 1",
|
|
||||||
"environmentVariables": {
|
|
||||||
"NODE_ENV": "development"
|
|
||||||
},
|
|
||||||
"prependPath":["/foo/bar", "bar/foo"]
|
|
||||||
"userMountVolumes:[
|
|
||||||
{
|
|
||||||
"sourceVolumePath": "my_docker_volume",
|
|
||||||
"targetVolumePath": "/volume_mount",
|
|
||||||
"readOnly": false
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"mountVolumes": [
|
|
||||||
{
|
|
||||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work",
|
|
||||||
"targetVolumePath": "/__w",
|
|
||||||
"readOnly": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/externals",
|
|
||||||
"targetVolumePath": "/__e",
|
|
||||||
"readOnly": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_temp",
|
|
||||||
"targetVolumePath": "/__w/_temp",
|
|
||||||
"readOnly": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_actions",
|
|
||||||
"targetVolumePath": "/__w/_actions",
|
|
||||||
"readOnly": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_tool",
|
|
||||||
"targetVolumePath": "/__w/_tool",
|
|
||||||
"readOnly": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_temp/_github_home",
|
|
||||||
"targetVolumePath": "/github/home",
|
|
||||||
"readOnly": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_temp/_github_workflow",
|
|
||||||
"targetVolumePath": "/github/workflow",
|
|
||||||
"readOnly": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"registry": null,
|
|
||||||
"portMappings": { "80": "801" }
|
|
||||||
},
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Example Input for dockerfile</summary>
|
|
||||||
<br>
|
|
||||||
|
|
||||||
```
|
|
||||||
"command": "run_container_step",
|
|
||||||
"responseFile": null,
|
|
||||||
"state":
|
|
||||||
{
|
|
||||||
"network": "github_network_53269bd575974817b43f4733536b200c",
|
|
||||||
"jobContainer" : "82e8219701fe096a35941d869cf8d71af1d943b5d3bdd718850fb87ac3042480",
|
|
||||||
"services":
|
|
||||||
{
|
|
||||||
"redis": "60972d9aa486605e66b0dad4abb638dc3d9116f566579e418166eedb8abb9105"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"args":
|
|
||||||
{
|
|
||||||
"image": null,
|
|
||||||
"dockerfile": /__w/_actions/foo/dockerfile,
|
|
||||||
"entryPointArgs": ["hello world"],
|
|
||||||
"entryPoint": "echo",
|
|
||||||
"workingDirectory": "/__w/thboop-test2/thboop-test2",
|
|
||||||
"createOptions": "--cpus 1",
|
|
||||||
"environmentVariables": {
|
|
||||||
"NODE_ENV": "development"
|
|
||||||
},
|
|
||||||
"prependPath":["/foo/bar", "bar/foo"]
|
|
||||||
"userMountVolumes:[
|
|
||||||
{
|
|
||||||
"sourceVolumePath": "my_docker_volume",
|
|
||||||
"targetVolumePath": "/volume_mount",
|
|
||||||
"readOnly": false
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"mountVolumes": [
|
|
||||||
{
|
|
||||||
"sourceVolumePath": "my_docker_volume",
|
|
||||||
"targetVolumePath": "/volume_mount",
|
|
||||||
"readOnly": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work",
|
|
||||||
"targetVolumePath": "/__w",
|
|
||||||
"readOnly": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/externals",
|
|
||||||
"targetVolumePath": "/__e",
|
|
||||||
"readOnly": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_temp",
|
|
||||||
"targetVolumePath": "/__w/_temp",
|
|
||||||
"readOnly": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_actions",
|
|
||||||
"targetVolumePath": "/__w/_actions",
|
|
||||||
"readOnly": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_tool",
|
|
||||||
"targetVolumePath": "/__w/_tool",
|
|
||||||
"readOnly": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_temp/_github_home",
|
|
||||||
"targetVolumePath": "/github/home",
|
|
||||||
"readOnly": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sourceVolumePath": "/home/thomas/git/runner/_layout/_work/_temp/_github_workflow",
|
|
||||||
"targetVolumePath": "/github/workflow",
|
|
||||||
"readOnly": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"registry": null,
|
|
||||||
"portMappings": [ "8080:80/tcp", "8080:80/udp" ]
|
|
||||||
},
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Field Descriptions</summary>
|
|
||||||
<br>
|
|
||||||
|
|
||||||
```
|
|
||||||
Arg Fields:
|
|
||||||
|
|
||||||
|
|
||||||
"image": **Optional** A string containing the docker image. Otherwise a dockerfile must be provided
|
|
||||||
"dockerfile": **Optional** A string containing the path to the dockerfile, otherwise an image must be provided
|
|
||||||
"entryPointArgs": **Optional** A list containing the entry point args
|
|
||||||
"entryPoint": **Optional** The container entry point to use if the default image entrypoint should be overwritten
|
|
||||||
"workingDirectory": **Required** A string containing the absolute path of the working directory
|
|
||||||
"createOptions": **Optional** The optional create options specified in the [YAML](https://docs.github.com/en/actions/using-jobs/running-jobs-in-a-container#example-running-a-job-within-a-container)
|
|
||||||
"environmentVariables": **Optional** A map of key value env's to set
|
|
||||||
"prependPath": **Optional** an array of additional paths to prepend to the $PATH variable
|
|
||||||
"userMountVolumes: ** Optional** an array of user mount volumes set in the [YAML](https://docs.github.com/en/actions/using-jobs/running-jobs-in-a-container#example-running-a-job-within-a-container)
|
|
||||||
"sourceVolumePath": **Required** The source path to the volume to be mounted into the docker container
|
|
||||||
"targetVolumePath": **Required** The target path to the volume to be mounted into the docker container
|
|
||||||
"readOnly": false **Required** whether or not the mount should be read only
|
|
||||||
"mountVolumes": **Required** an array of mounts to mount into the container, same fields as above
|
|
||||||
"sourceVolumePath": **Required** The source path to the volume to be mounted into the docker container
|
|
||||||
"targetVolumePath": **Required** The target path to the volume to be mounted into the docker container
|
|
||||||
"readOnly": false **Required** whether or not the mount should be read only
|
|
||||||
"registry" **Optional** docker registry credentials to use when using a private container registry
|
|
||||||
"username": **Optional** the username
|
|
||||||
"password": **Optional** the password
|
|
||||||
"serverUrl": **Optional** the registry url
|
|
||||||
"portMappings": **Optional** an array of source:target ports to map into the container
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
No output is expected
|
|
||||||
|
|
||||||
Currently we build all container actions at the start of the job. By doing it during the hook, we move this to just in time building for hooks. We could expose a hook to build/pull a container action, and have those called at the start of a job, but doing so would require hook authors to track the build containers in the state, which could be painful.
|
|
||||||
|
|
||||||
### Run Script Step
|
|
||||||
The `run_script_step` expects you to:
|
|
||||||
- Invoke the provided script inside the job container and return the exit code
|
|
||||||
- Stream any step log output to stdout and stderr
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Example Input</summary>
|
|
||||||
<br>
|
|
||||||
|
|
||||||
|
|
||||||
```
|
|
||||||
"command": "run_script_step",
|
|
||||||
"responseFile": null,
|
|
||||||
"state":
|
|
||||||
{
|
|
||||||
"network": "github_network_53269bd575974817b43f4733536b200c",
|
|
||||||
"jobContainer" : "82e8219701fe096a35941d869cf8d71af1d943b5d3bdd718850fb87ac3042480",
|
|
||||||
"serviceContainers":
|
|
||||||
{
|
|
||||||
"redis": "60972d9aa486605e66b0dad4abb638dc3d9116f566579e418166eedb8abb9105"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"args":
|
|
||||||
{
|
|
||||||
"entryPointArgs": ["-e", "/runner/temp/abc123.sh"],
|
|
||||||
"entryPoint": "bash",
|
|
||||||
"environmentVariables": {
|
|
||||||
"NODE_ENV": "development"
|
|
||||||
},
|
|
||||||
"prependPath": ["/foo/bar", "bar/foo"],
|
|
||||||
"workingDirectory": "/__w/thboop-test2/thboop-test2"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Field Descriptions</summary>
|
|
||||||
<br>
|
|
||||||
|
|
||||||
```
|
|
||||||
Arg Fields:
|
|
||||||
|
|
||||||
|
|
||||||
"entryPointArgs": **Optional** A list containing the entry point args
|
|
||||||
"entryPoint": **Optional** The container entry point to use if the default image entrypoint should be overwritten
|
|
||||||
"prependPath": **Optional** an array of additional paths to prepend to the $PATH variable
|
|
||||||
"workingDirectory": **Required** A string containing the absolute path of the working directory
|
|
||||||
"environmentVariables": **Optional** A map of key value env's to set
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
No output is expected
|
|
||||||
|
|
||||||
|
|
||||||
## Limitations
|
|
||||||
- We will only support linux on launch
|
|
||||||
- Hooks are set by the runner admin, and thus are only supported on self hosted runners
|
|
||||||
|
|
||||||
## Consequences
|
|
||||||
- We support non docker scenarios for self hosted runners and allow customers to customize their docker invocations
|
|
||||||
- We ship/maintain docs on docker hooks and an open source repo with examples
|
|
||||||
- We support these hooks and add enough telemetry to be able to troubleshoot support issues as they come in.
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
# ADR 2494: Runner Image Tags
|
|
||||||
|
|
||||||
**Date**: 2023-03-17
|
|
||||||
|
|
||||||
**Status**: Accepted<!-- |Accepted|Rejected|Superceded|Deprecated -->
|
|
||||||
|
|
||||||
## Context
|
|
||||||
|
|
||||||
Following the [adoption of actions-runner-controller by GitHub](https://github.com/actions/actions-runner-controller/discussions/2072) and the introduction of the new runner scale set autoscaling mode, we needed to provide a basic runner image that could be used off the shelf without much friction.
|
|
||||||
|
|
||||||
The [current runner image](https://github.com/actions/runner/pkgs/container/actions-runner) is published to GHCR. Each release of this image is tagged with the runner version and the most recent release is also tagged with `latest`.
|
|
||||||
|
|
||||||
While the use of `latest` is common practice, we recommend that users pin a specific version of the runner image for a predictable runtime and improved security posture. However, we still notice that a large number of end users are relying on the `latest` tag & raising issues when they encounter problems.
|
|
||||||
|
|
||||||
Add to that, the community actions-runner-controller maintainers have issued a [deprecation notice](https://github.com/actions/actions-runner-controller/issues/2056) of the `latest` tag for the existing runner images (https://github.com/orgs/actions-runner-controller/packages).
|
|
||||||
|
|
||||||
## Decision
|
|
||||||
|
|
||||||
Proceed with Option 2, keeping the `latest` tag and adding the `NOTES.txt` file to our helm charts with the notice.
|
|
||||||
|
|
||||||
### Option 1: Remove the `latest` tag
|
|
||||||
|
|
||||||
By removing the `latest` tag, we have to proceed with either of these options:
|
|
||||||
|
|
||||||
1. Remove the runner image reference in the `values.yaml` provided with the `gha-runner-scale-set` helm chart and mark these fields as required so that users have to explicitly specify a runner image and a specific tag. This will obviously introduce more friction for users who want to start using actions-runner-controller for the first time.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: runner
|
|
||||||
image: ""
|
|
||||||
tag: ""
|
|
||||||
command: ["/home/runner/run.sh"]
|
|
||||||
```
|
|
||||||
|
|
||||||
1. Pin a specific runner image tag in the `values.yaml` provided with the `gha-runner-scale-set` helm chart. This will reduce friction for users who want to start using actions-runner-controller for the first time but will require us to update the `values.yaml` with every new runner release.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: runner
|
|
||||||
image: "ghcr.io/actions/actions-runner"
|
|
||||||
tag: "v2.300.0"
|
|
||||||
command: ["/home/runner/run.sh"]
|
|
||||||
```
|
|
||||||
|
|
||||||
### Option 2: Keep the `latest` tag
|
|
||||||
|
|
||||||
Keeping the `latest` tag is also a reasonable option especially if we don't expect to make any breaking changes to the runner image. We could enhance this by adding a [NOTES.txt](https://helm.sh/docs/chart_template_guide/notes_files/) to the helm chart which will be displayed to the user after a successful helm install/upgrade. This will help users understand the implications of using the `latest` tag and how to pin a specific version of the runner image.
|
|
||||||
|
|
||||||
The runner image release workflow will need to be updated so that the image is pushed to GHCR and tagged only when the runner rollout has reached all scale units.
|
|
||||||
|
|
||||||
## Consequences
|
|
||||||
|
|
||||||
Proceeding with **option 1** means:
|
|
||||||
|
|
||||||
1. We will enhance the runtime predictability and security posture of our end users
|
|
||||||
1. We will have to update the `values.yaml` with every new runner release (that can be automated)
|
|
||||||
1. We will introduce friction for users who want to start using actions-runner-controller for the first time
|
|
||||||
|
|
||||||
Proceeding with **option 2** means:
|
|
||||||
|
|
||||||
1. We will have to continue to maintain the `latest` tag
|
|
||||||
1. We will assume that end users will be able to handle the implications of using the `latest` tag
|
|
||||||
1. Runner image release workflow needs to be updated
|
|
||||||
@@ -11,7 +11,7 @@ export RUNNER_CFG_PAT=yourPAT
|
|||||||
|
|
||||||
## Create running as a service
|
## Create running as a service
|
||||||
|
|
||||||
**Scenario**: Run on a machine or VM ([not container](#why-cant-i-use-a-container)) which automates:
|
**Scenario**: Run on a machine or VM (not container) which automates:
|
||||||
|
|
||||||
- Resolving latest released runner
|
- Resolving latest released runner
|
||||||
- Download and extract latest
|
- Download and extract latest
|
||||||
@@ -21,35 +21,14 @@ export RUNNER_CFG_PAT=yourPAT
|
|||||||
|
|
||||||
:point_right: [Sample script here](../scripts/create-latest-svc.sh) :point_left:
|
:point_right: [Sample script here](../scripts/create-latest-svc.sh) :point_left:
|
||||||
|
|
||||||
Run as a one-liner. NOTE: replace with yourorg/yourrepo (repo level) or just yourorg (org level)
|
Run as a one-liner. NOTE: replace with yourorg/yourrepo (repo level) or just yourorg (org level)
|
||||||
```bash
|
```bash
|
||||||
curl -s https://raw.githubusercontent.com/actions/runner/main/scripts/create-latest-svc.sh | bash -s yourorg/yourrepo
|
curl -s https://raw.githubusercontent.com/actions/runner/automate/scripts/create-latest-svc.sh | bash -s yourorg/yourrepo
|
||||||
```
|
```
|
||||||
|
|
||||||
You can call the script with additional arguments:
|
## Uninstall running as service
|
||||||
```bash
|
|
||||||
# Usage:
|
|
||||||
# export RUNNER_CFG_PAT=<yourPAT>
|
|
||||||
# ./create-latest-svc -s scope -g [ghe_domain] -n [name] -u [user] -l [labels]
|
|
||||||
# -s required scope: repo (:owner/:repo) or org (:organization)
|
|
||||||
# -g optional ghe_hostname: the fully qualified domain name of your GitHub Enterprise Server deployment
|
|
||||||
# -n optional name of the runner, defaults to hostname
|
|
||||||
# -u optional user svc will run as, defaults to current
|
|
||||||
# -l optional list of labels (split by comma) applied on the runner"
|
|
||||||
```
|
|
||||||
|
|
||||||
Use `--` to pass any number of optional named parameters:
|
**Scenario**: Run on a machine or VM (not container) which automates:
|
||||||
|
|
||||||
```
|
|
||||||
curl -s https://raw.githubusercontent.com/actions/runner/main/scripts/create-latest-svc.sh | bash -s -- -s myorg/myrepo -n myname -l label1,label2
|
|
||||||
```
|
|
||||||
### Why can't I use a container?
|
|
||||||
|
|
||||||
The runner is installed as a service using `systemd` and `systemctl`. Docker does not support `systemd` for service configuration on a container.
|
|
||||||
|
|
||||||
## Uninstall running as service
|
|
||||||
|
|
||||||
**Scenario**: Run on a machine or VM ([not container](#why-cant-i-use-a-container)) which automates:
|
|
||||||
|
|
||||||
- Stops and uninstalls the systemd (linux) or Launchd (osx) service
|
- Stops and uninstalls the systemd (linux) or Launchd (osx) service
|
||||||
- Acquires a removal token
|
- Acquires a removal token
|
||||||
@@ -57,9 +36,9 @@ The runner is installed as a service using `systemd` and `systemctl`. Docker doe
|
|||||||
|
|
||||||
:point_right: [Sample script here](../scripts/remove-svc.sh) :point_left:
|
:point_right: [Sample script here](../scripts/remove-svc.sh) :point_left:
|
||||||
|
|
||||||
Repo level one liner. NOTE: replace with yourorg/yourrepo (repo level) or just yourorg (org level)
|
Repo level one liner. NOTE: replace with yourorg/yourrepo (repo level) or just yourorg (org level)
|
||||||
```bash
|
```bash
|
||||||
curl -s https://raw.githubusercontent.com/actions/runner/main/scripts/remove-svc.sh | bash -s yourorg/yourrepo
|
curl -s https://raw.githubusercontent.com/actions/runner/automate/scripts/remove-svc.sh | bash -s yourorg/yourrepo
|
||||||
```
|
```
|
||||||
|
|
||||||
### Delete an offline runner
|
### Delete an offline runner
|
||||||
@@ -74,5 +53,5 @@ curl -s https://raw.githubusercontent.com/actions/runner/main/scripts/remove-svc
|
|||||||
|
|
||||||
Repo level one-liner. NOTE: replace with yourorg/yourrepo (repo level) or just yourorg (org level) and replace runnername
|
Repo level one-liner. NOTE: replace with yourorg/yourrepo (repo level) or just yourorg (org level) and replace runnername
|
||||||
```bash
|
```bash
|
||||||
curl -s https://raw.githubusercontent.com/actions/runner/main/scripts/delete.sh | bash -s yourorg/yourrepo runnername
|
curl -s https://raw.githubusercontent.com/actions/runner/automate/scripts/delete.sh | bash -s yourorg/yourrepo runnername
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,83 +0,0 @@
|
|||||||
|
|
||||||
# Actions Connection Check
|
|
||||||
|
|
||||||
## What is this check for?
|
|
||||||
|
|
||||||
Make sure the runner has access to actions service for GitHub.com or GitHub Enterprise Server
|
|
||||||
|
|
||||||
- For GitHub.com
|
|
||||||
- The runner needs to access `https://api.github.com` for downloading actions.
|
|
||||||
- The runner needs to access `https://codeload.github.com` for downloading actions tar.gz/zip.
|
|
||||||
- The runner needs to access `https://vstoken.actions.githubusercontent.com/_apis/.../` for requesting an access token.
|
|
||||||
- The runner needs to access `https://pipelines.actions.githubusercontent.com/_apis/.../` for receiving workflow jobs.
|
|
||||||
- The runner needs to access `https://results-receiver.actions.githubusercontent.com/.../` for reporting progress and uploading logs during a workflow job execution.
|
|
||||||
---
|
|
||||||
**NOTE:** for the full list of domains that are required to be in the firewall allow list refer to the [GitHub self-hosted runners requirements documentation](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners#communication-between-self-hosted-runners-and-github).
|
|
||||||
|
|
||||||
These can by tested by running the following `curl` commands from your self-hosted runner machine:
|
|
||||||
|
|
||||||
```
|
|
||||||
curl -v https://api.github.com/zen
|
|
||||||
curl -v https://codeload.github.com/_ping
|
|
||||||
curl -v https://vstoken.actions.githubusercontent.com/_apis/health
|
|
||||||
curl -v https://pipelines.actions.githubusercontent.com/_apis/health
|
|
||||||
curl -v https://results-receiver.actions.githubusercontent.com/health
|
|
||||||
```
|
|
||||||
|
|
||||||
- For GitHub Enterprise Server
|
|
||||||
- The runner needs to access `https://[hostname]/api/v3` for downloading actions.
|
|
||||||
- The runner needs to access `https://codeload.[hostname]/_ping` for downloading actions tar.gz/zip.
|
|
||||||
- The runner needs to access `https://[hostname]/_services/vstoken/_apis/.../` for requesting an access token.
|
|
||||||
- The runner needs to access `https://[hostname]/_services/pipelines/_apis/.../` for receiving workflow jobs.
|
|
||||||
|
|
||||||
These can by tested by running the following `curl` commands from your self-hosted runner machine, replacing `[hostname]` with the hostname of your appliance, for instance `github.example.com`:
|
|
||||||
|
|
||||||
```
|
|
||||||
curl -v https://[hostname]/api/v3/zen
|
|
||||||
curl -v https://codeload.[hostname]/_ping
|
|
||||||
curl -v https://[hostname]/_services/vstoken/_apis/health
|
|
||||||
curl -v https://[hostname]/_services/pipelines/_apis/health
|
|
||||||
```
|
|
||||||
|
|
||||||
A common cause of this these connectivity issues is if your to GitHub Enterprise Server appliance is using [the self-signed certificate that is enabled the first time](https://docs.github.com/en/enterprise-server/admin/configuration/configuring-network-settings/configuring-tls) your appliance is started. As self-signed certificates are not trusted by web browsers and Git clients, these clients (including the GitHub Actions runner) will report certificate warnings.
|
|
||||||
|
|
||||||
We recommend [upload a certificate signed by a trusted authority](https://docs.github.com/en/enterprise-server/admin/configuration/configuring-network-settings/configuring-tls) to GitHub Enterprise Server, or enabling the built-in ][Let's Encrypt support](https://docs.github.com/en/enterprise-server/admin/configuration/configuring-network-settings/configuring-tls).
|
|
||||||
|
|
||||||
|
|
||||||
## What is checked?
|
|
||||||
|
|
||||||
- DNS lookup for api.github.com or myGHES.com using dotnet
|
|
||||||
- Ping api.github.com or myGHES.com using dotnet
|
|
||||||
- Make HTTP GET to https://api.github.com or https://myGHES.com/api/v3 using dotnet, check response headers contains `X-GitHub-Request-Id`
|
|
||||||
---
|
|
||||||
- DNS lookup for codeload.github.com or codeload.myGHES.com using dotnet
|
|
||||||
- Ping codeload.github.com or codeload.myGHES.com using dotnet
|
|
||||||
- Make HTTP GET to https://codeload.github.com/_ping or https://codeload.myGHES.com/_ping using dotnet, check response headers contains `X-GitHub-Request-Id`
|
|
||||||
---
|
|
||||||
- DNS lookup for vstoken.actions.githubusercontent.com using dotnet
|
|
||||||
- Ping vstoken.actions.githubusercontent.com using dotnet
|
|
||||||
- Make HTTP GET to https://vstoken.actions.githubusercontent.com/_apis/health or https://myGHES.com/_services/vstoken/_apis/health using dotnet, check response headers contains `x-vss-e2eid`
|
|
||||||
---
|
|
||||||
- DNS lookup for pipelines.actions.githubusercontent.com using dotnet
|
|
||||||
- Ping pipelines.actions.githubusercontent.com using dotnet
|
|
||||||
- Make HTTP GET to https://pipelines.actions.githubusercontent.com/_apis/health or https://myGHES.com/_services/pipelines/_apis/health using dotnet, check response headers contains `x-vss-e2eid`
|
|
||||||
- Make HTTP POST to https://pipelines.actions.githubusercontent.com/_apis/health or https://myGHES.com/_services/pipelines/_apis/health using dotnet, check response headers contains `x-vss-e2eid`
|
|
||||||
---
|
|
||||||
- DNS lookup for results-receiver.actions.githubusercontent.com using dotnet
|
|
||||||
- Ping results-receiver.actions.githubusercontent.com using dotnet
|
|
||||||
- Make HTTP GET to https://results-receiver.actions.githubusercontent.com/health using dotnet, check response headers contains `X-GitHub-Request-Id`
|
|
||||||
|
|
||||||
## How to fix the issue?
|
|
||||||
|
|
||||||
### 1. Check the common network issue
|
|
||||||
|
|
||||||
> Please check the [network doc](./network.md)
|
|
||||||
|
|
||||||
### 2. SSL certificate related issue
|
|
||||||
|
|
||||||
If you are seeing `System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.` in the log, it means the runner can't connect to Actions service due to SSL handshake failure.
|
|
||||||
> Please check the [SSL cert doc](./sslcert.md)
|
|
||||||
|
|
||||||
## Still not working?
|
|
||||||
|
|
||||||
Contact [GitHub Support](https://support.github.com) if you have further questuons, or log an issue at https://github.com/actions/runner if you think it's a runner issue.
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
# Git Connection Check
|
|
||||||
|
|
||||||
## What is this check for?
|
|
||||||
|
|
||||||
Make sure `git` can access GitHub.com or your GitHub Enterprise Server.
|
|
||||||
|
|
||||||
|
|
||||||
## What is checked?
|
|
||||||
|
|
||||||
The test is done by executing
|
|
||||||
```bash
|
|
||||||
# For GitHub.com
|
|
||||||
git ls-remote --exit-code https://github.com/actions/checkout HEAD
|
|
||||||
|
|
||||||
# For GitHub Enterprise Server
|
|
||||||
git ls-remote --exit-code https://ghes.me/actions/checkout HEAD
|
|
||||||
```
|
|
||||||
|
|
||||||
The test also set environment variable `GIT_TRACE=1` and `GIT_CURL_VERBOSE=1` before running `git ls-remote`, this will make `git` to produce debug log for better debug any potential issues.
|
|
||||||
|
|
||||||
## How to fix the issue?
|
|
||||||
|
|
||||||
### 1. Check global and system git config
|
|
||||||
|
|
||||||
If you are having issues connecting to the server, check your global and system git config for any unexpected authentication headers. You might be seeing an error like:
|
|
||||||
|
|
||||||
```
|
|
||||||
fatal: unable to access 'https://github.com/actions/checkout/': The requested URL returned error: 400
|
|
||||||
```
|
|
||||||
|
|
||||||
The following commands can be used to check for unexpected authentication headers:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ git config --global --list | grep extraheader
|
|
||||||
http.extraheader=AUTHORIZATION: unexpected_auth_header
|
|
||||||
|
|
||||||
$ git config --system --list | grep extraheader
|
|
||||||
```
|
|
||||||
|
|
||||||
The following command can be used to remove the above value: `git config --global --unset http.extraheader`
|
|
||||||
|
|
||||||
### 2. Check the common network issue
|
|
||||||
|
|
||||||
> Please check the [network doc](./network.md)
|
|
||||||
|
|
||||||
### 3. SSL certificate related issue
|
|
||||||
|
|
||||||
If you are seeing `SSL Certificate problem:` in the log, it means the `git` can't connect to the GitHub server due to SSL handshake failure.
|
|
||||||
> Please check the [SSL cert doc](./sslcert.md)
|
|
||||||
|
|
||||||
## Still not working?
|
|
||||||
|
|
||||||
Contact GitHub customer service or log an issue at https://github.com/actions/runner if you think it's a runner issue.
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
# Internet Connection Check
|
|
||||||
|
|
||||||
## What is this check for?
|
|
||||||
|
|
||||||
Make sure the runner has access to https://api.github.com
|
|
||||||
|
|
||||||
The runner needs to access https://api.github.com to download any actions from the marketplace.
|
|
||||||
|
|
||||||
Even the runner is configured to GitHub Enterprise Server, the runner can still download actions from GitHub.com with [GitHub Connect](https://docs.github.com/en/enterprise-server@2.22/admin/github-actions/enabling-automatic-access-to-githubcom-actions-using-github-connect)
|
|
||||||
|
|
||||||
|
|
||||||
## What is checked?
|
|
||||||
|
|
||||||
- DNS lookup for api.github.com using dotnet
|
|
||||||
- Ping api.github.com using dotnet
|
|
||||||
- Make HTTP GET to https://api.github.com using dotnet, check response headers contains `X-GitHub-Request-Id`
|
|
||||||
|
|
||||||
## How to fix the issue?
|
|
||||||
|
|
||||||
### 1. Check the common network issue
|
|
||||||
|
|
||||||
> Please check the [network doc](./network.md)
|
|
||||||
|
|
||||||
## Still not working?
|
|
||||||
|
|
||||||
Contact GitHub customer service or log an issue at https://github.com/actions/runner if you think it's a runner issue.
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
## Common Network Related Issues
|
|
||||||
|
|
||||||
### Common things that can cause the runner to not working properly
|
|
||||||
|
|
||||||
- A bug in the runner or the dotnet framework that causes the actions runner to be unable to make Http requests in a certain network environment.
|
|
||||||
|
|
||||||
- A Proxy or Firewall may block certain HTTP method, such as blocking all POST and PUT calls which the runner will use to upload logs.
|
|
||||||
|
|
||||||
- A Proxy or Firewall may only allows requests with certain user-agent to pass through and the actions runner user-agent is not in the allow list.
|
|
||||||
|
|
||||||
- A Proxy try to decrypt and exam HTTPS traffic for security purpose but cause the actions-runner to fail to finish SSL handshake due to the lack of trusting proxy's CA.
|
|
||||||
|
|
||||||
- The SSL handshake may fail if the client and server do not support the same TLS version, or the same cipher suites.
|
|
||||||
|
|
||||||
- A Proxy may try to modify the HTTPS request (like add or change some http headers) and causes the request become incompatible with the Actions Service (ASP.NetCore), Ex: [Nginx](https://github.com/dotnet/aspnetcore/issues/17081)
|
|
||||||
|
|
||||||
- Firewall rules that block action runner from accessing [certain hosts](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners#communication-between-self-hosted-runners-and-github), ex: `*.github.com`, `*.actions.githubusercontent.com`, etc
|
|
||||||
|
|
||||||
|
|
||||||
### Identify and solve these problems
|
|
||||||
|
|
||||||
The key is to figure out where is the problem, the network environment, or the actions runner?
|
|
||||||
|
|
||||||
Use a 3rd party tool to make the same requests as the runner did would be a good start point.
|
|
||||||
|
|
||||||
- Use `nslookup` to check DNS
|
|
||||||
- Use `ping` to check Ping
|
|
||||||
- Use `traceroute`, `tracepath`, or `tracert` to check the network route between the runner and the Actions service
|
|
||||||
- Use `curl -v` to check the network stack, good for verifying default certificate/proxy settings.
|
|
||||||
- Use `Invoke-WebRequest` from `pwsh` (`PowerShell Core`) to check the dotnet network stack, good for verifying bugs in the dotnet framework.
|
|
||||||
|
|
||||||
If the 3rd party tool is also experiencing the same error as the runner does, then you might want to contact your network administrator for help.
|
|
||||||
|
|
||||||
Otherwise, contact GitHub customer support or log an issue at https://github.com/actions/runner
|
|
||||||
|
|
||||||
### Troubleshooting: Why can't I configure a runner?
|
|
||||||
|
|
||||||
If you are having trouble connecting, try these steps:
|
|
||||||
|
|
||||||
1. Validate you can reach our endpoints from your web browser. If not, double check your local network connection
|
|
||||||
- For hosted Github:
|
|
||||||
- https://api.github.com/
|
|
||||||
- https://vstoken.actions.githubusercontent.com/_apis/health
|
|
||||||
- https://pipelines.actions.githubusercontent.com/_apis/health
|
|
||||||
- https://results-receiver.actions.githubusercontent.com/health
|
|
||||||
- For GHES/GHAE
|
|
||||||
- https://myGHES.com/_services/vstoken/_apis/health
|
|
||||||
- https://myGHES.com/_services/pipelines/_apis/health
|
|
||||||
- https://myGHES.com/api/v3
|
|
||||||
2. Validate you can reach those endpoints in powershell core
|
|
||||||
- The runner runs on .net core, lets validate the local settings for that stack
|
|
||||||
- Open up `pwsh`
|
|
||||||
- Run the command using the urls above `Invoke-WebRequest {url}`
|
|
||||||
3. If not, get a packet trace using a tool like wireshark and start looking at the TLS handshake.
|
|
||||||
- If you see a Client Hello followed by a Server RST:
|
|
||||||
- You may need to configure your TLS settings to use the correct version
|
|
||||||
- You should support TLS version 1.2 or later
|
|
||||||
- You may need to configure your TLS settings to have up to date cipher suites, this may be solved by system updates and patches.
|
|
||||||
- Most notably, on windows server 2012 make sure [the tls cipher suite update](https://support.microsoft.com/en-us/topic/update-adds-new-tls-cipher-suites-and-changes-cipher-suite-priorities-in-windows-8-1-and-windows-server-2012-r2-8e395e43-c8ef-27d8-b60c-0fc57d526d94) is installed
|
|
||||||
- Your firewall, proxy or network configuration may be blocking the connection
|
|
||||||
- You will want to reach out to whoever is in charge of your network with these pcap files to further troubleshoot
|
|
||||||
- If you see a failure later in the handshake:
|
|
||||||
- Try the fix in the [SSLCert Fix](./sslcert.md)
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
# Node.js Connection Check
|
|
||||||
|
|
||||||
## What is this check for?
|
|
||||||
|
|
||||||
Make sure the built-in node.js has access to GitHub.com or GitHub Enterprise Server.
|
|
||||||
|
|
||||||
The runner carries its own copies of node.js executables under `<runner_root>/externals/node20/` and `<runner_root>/externals/node24/`.
|
|
||||||
|
|
||||||
All javascript base Actions will get executed by the built-in `node` at either `<runner_root>/externals/node20/` or `<runner_root>/externals/node24/` depending on the version specified in the action's metadata.
|
|
||||||
|
|
||||||
> Not the `node` from `$PATH`
|
|
||||||
|
|
||||||
## What is checked?
|
|
||||||
|
|
||||||
- Make HTTPS GET to https://api.github.com or https://myGHES.com/api/v3 using node.js, make sure it gets 200 response code.
|
|
||||||
|
|
||||||
## How to fix the issue?
|
|
||||||
|
|
||||||
### 1. Check the common network issue
|
|
||||||
|
|
||||||
> Please check the [network doc](./network.md)
|
|
||||||
|
|
||||||
### 2. SSL certificate related issue
|
|
||||||
|
|
||||||
If you are seeing `Https request failed due to SSL cert issue` in the log, it means the `node.js` can't connect to the GitHub server due to SSL handshake failure.
|
|
||||||
> Please check the [SSL cert doc](./sslcert.md)
|
|
||||||
|
|
||||||
## Still not working?
|
|
||||||
|
|
||||||
Contact GitHub customer service or log an issue at https://github.com/actions/runner if you think it's a runner issue.
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
## SSL Certificate Related Issues
|
|
||||||
|
|
||||||
You might run into an SSL certificate error when your GitHub Enterprise Server is using a self-signed SSL server certificate or a web proxy within your network is decrypting HTTPS traffic for a security audit.
|
|
||||||
|
|
||||||
As long as your certificate is generated properly, most of the issues should be fixed after your trust the certificate properly on the runner machine.
|
|
||||||
|
|
||||||
> Different OS might have extra requirements on SSL certificate,
|
|
||||||
> Ex: macOS requires `ExtendedKeyUsage` https://support.apple.com/en-us/HT210176
|
|
||||||
|
|
||||||
### Don't skip SSL cert validation
|
|
||||||
|
|
||||||
> !!! DO NOT SKIP SSL CERT VALIDATION !!!
|
|
||||||
> !!! IT IS A BAD SECURITY PRACTICE !!!
|
|
||||||
|
|
||||||
### Download SSL certificate chain
|
|
||||||
|
|
||||||
Depends on how your SSL server certificate gets configured, you might need to download the whole certificate chain from a machine that has trusted the SSL certificate's CA.
|
|
||||||
|
|
||||||
- Approach 1: Download certificate chain using a browser (Chrome, Firefox, IT), you can google for more example, [here is what I found](https://medium.com/@menakajain/export-download-ssl-certificate-from-server-site-url-bcfc41ea46a2)
|
|
||||||
|
|
||||||
- Approach 2: Download certificate chain using OpenSSL, you can google for more example, [here is what I found](https://superuser.com/a/176721)
|
|
||||||
|
|
||||||
- Approach 3: Ask your network administrator or the owner of the CA certificate to send you a copy of it
|
|
||||||
|
|
||||||
### Trust CA certificate for the Runner
|
|
||||||
|
|
||||||
The actions runner is a dotnet core application which will follow how dotnet load SSL CA certificates on each OS.
|
|
||||||
|
|
||||||
You can get full details documentation at [here](https://docs.microsoft.com/en-us/dotnet/standard/security/cross-platform-cryptography#x509store)
|
|
||||||
|
|
||||||
In short:
|
|
||||||
- Windows: Load from Windows certificate store.
|
|
||||||
- Linux: Load from OpenSSL CA cert bundle.
|
|
||||||
- macOS: Load from macOS KeyChain.
|
|
||||||
|
|
||||||
To let the runner trusts your CA certificate, you will need to:
|
|
||||||
1. Save your SSL certificate chain which includes the root CA and all intermediate CAs into a `.pem` file.
|
|
||||||
2. Use `OpenSSL` to convert `.pem` file to a proper format for different OS, here is some [doc with sample commands](https://www.sslshopper.com/ssl-converter.html)
|
|
||||||
3. Trust CA on different OS:
|
|
||||||
- Windows: https://docs.microsoft.com/en-us/skype-sdk/sdn/articles/installing-the-trusted-root-certificate
|
|
||||||
- macOS: 
|
|
||||||
- Linux: Refer to the distribution documentation
|
|
||||||
1. RedHat: https://www.redhat.com/sysadmin/ca-certificates-cli
|
|
||||||
2. Ubuntu: http://manpages.ubuntu.com/manpages/focal/man8/update-ca-certificates.8.html
|
|
||||||
3. Google search: "trust ca certificate on [linux distribution]"
|
|
||||||
4. If all approaches failed, set environment variable `SSL_CERT_FILE` to the CA bundle `.pem` file we get.
|
|
||||||
> To verify cert gets installed properly on Linux, you can try use `curl -v https://sitewithsslissue.com` and `pwsh -Command \"Invoke-WebRequest -Uri https://sitewithsslissue.com\"`
|
|
||||||
|
|
||||||
### Trust CA certificate for Git CLI
|
|
||||||
|
|
||||||
Git uses various CA bundle file depends on your operation system.
|
|
||||||
- Git packaged the CA bundle file within the Git installation on Windows
|
|
||||||
- Git use OpenSSL certificate CA bundle file on Linux and macOS
|
|
||||||
|
|
||||||
You can check where Git check CA file by running:
|
|
||||||
```bash
|
|
||||||
export GIT_CURL_VERBOSE=1
|
|
||||||
git ls-remote https://github.com/actions/runner HEAD
|
|
||||||
```
|
|
||||||
|
|
||||||
You should see something like:
|
|
||||||
```
|
|
||||||
* Couldn't find host github.com in the .netrc file; using defaults
|
|
||||||
* Trying 140.82.114.4...
|
|
||||||
* TCP_NODELAY set
|
|
||||||
* Connected to github.com (140.82.114.4) port 443 (#0)
|
|
||||||
* ALPN, offering h2
|
|
||||||
* ALPN, offering http/1.1
|
|
||||||
* successfully set certificate verify locations:
|
|
||||||
* CAfile: /etc/ssl/cert.pem
|
|
||||||
CApath: none
|
|
||||||
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
|
|
||||||
```
|
|
||||||
This tells me `/etc/ssl/cert.pem` is where it read trusted CA certificates.
|
|
||||||
|
|
||||||
To let Git trusts your CA certificate, you will need to:
|
|
||||||
1. Save your SSL certificate chain which includes the root CA and all intermediate CAs into a `.pem` file.
|
|
||||||
2. Set `http.sslCAInfo` Git config or `GIT_SSL_CAINFO` environment variable to the full path of the `.pem` file [Git Doc](https://git-scm.com/docs/git-config#Documentation/git-config.txt-httpsslCAInfo)
|
|
||||||
> I would recommend using `http.sslCAInfo` since it can be scope to certain hosts that need the extra trusted CA.
|
|
||||||
> Ex: `git config --global http.https://myghes.com/.sslCAInfo /extra/ca/cert.pem`
|
|
||||||
> This will make Git use the `/extra/ca/cert.pem` only when communicates with `https://myghes.com` and keep using the default CA bundle with others.
|
|
||||||
|
|
||||||
### Trust CA certificate for Node.js
|
|
||||||
|
|
||||||
Node.js has compiled a snapshot of the Mozilla CA store that is fixed at each version of Node.js' release time.
|
|
||||||
|
|
||||||
To let Node.js trusts your CA certificate, you will need to:
|
|
||||||
1. Save your SSL certificate chain which includes the root CA and all intermediate CAs into a `.pem` file.
|
|
||||||
2. Set environment variable `NODE_EXTRA_CA_CERTS` which point to the file. ex: `export NODE_EXTRA_CA_CERTS=/full/path/to/cacert.pem` or `set NODE_EXTRA_CA_CERTS=C:\full\path\to\cacert.pem`
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# Contributions
|
# Contributions
|
||||||
|
|
||||||
We welcome contributions in the form of issues and pull requests. We view the contributions and the process as the same for github and external contributors. Please note the runner typically requires changes across the entire system and we aim for issues in the runner to be entirely self contained and fixable here. Therefore, we will primarily handle bug issues opened in this repo and we kindly request you to create all feature and enhancement requests on the [GitHub Feedback](https://github.com/community/community/discussions/categories/actions-and-packages) page.
|
We welcome contributions in the form of issues and pull requests. We view the contributions and the process as the same for github and external contributors.
|
||||||
|
|
||||||
> IMPORTANT: Building your own runner is critical for the dev inner loop process when contributing changes. However, only runners built and distributed by GitHub (releases) are supported in production. Be aware that workflows and orchestrations run service side with the runner being a remote process to run steps. For that reason, the service can pull the runner forward so customizations can be lost.
|
> IMPORTANT: Building your own runner is critical for the dev inner loop process when contributing changes. However, only runners built and distributed by GitHub (releases) are supported in production. Be aware that workflows and orchestrations run service side with the runner being a remote process to run steps. For that reason, the service can pull the runner forward so customizations can be lost.
|
||||||
|
|
||||||
@@ -12,49 +12,20 @@ Issues in this repository should be for the runner application. Note that the V
|
|||||||
|
|
||||||
## Enhancements and Feature Requests
|
## Enhancements and Feature Requests
|
||||||
|
|
||||||
We ask that before significant effort is put into code changes, that we have agreement on taking the change before time is invested in code changes.
|
We ask that before significant effort is put into code changes, that we have agreement on taking the change before time is invested in code changes.
|
||||||
|
|
||||||
1. Create a feature request. Once agreed we will take the enhancement
|
1. Create a feature request. Once agreed we will take the enhancment
|
||||||
2. Create an ADR to agree on the details of the change.
|
2. Create an ADR to agree on the details of the change.
|
||||||
|
|
||||||
An ADR is an Architectural Decision Record. This allows consensus on the direction forward and also serves as a record of the change and motivation. [Read more here](adrs/README.md)
|
An ADR is an Architectural Decision Record. This allows consensus on the direction forward and also serves as a record of the change and motivation. [Read more here](adrs/README.md)
|
||||||
|
|
||||||
## Required Dev Dependencies
|
## Development Life Cycle
|
||||||
|
|
||||||
|
### Required Dev Dependencies
|
||||||
|
|
||||||
  Git for Windows and Linux [Install Here](https://git-scm.com/downloads) (needed for dev sh script)
|
  Git for Windows and Linux [Install Here](https://git-scm.com/downloads) (needed for dev sh script)
|
||||||
|
|
||||||
 cURL [Install here](https://curl.se/download.html) (needed for external sh script)
|
### To Build, Test, Layout
|
||||||
|
|
||||||
 Visual Studio 2017 or newer [Install here](https://visualstudio.microsoft.com) (needed for dev sh script)
|
|
||||||
|
|
||||||
 Visual Studio 2022 17.3 Preview or later. [Install here](https://docs.microsoft.com/en-us/visualstudio/releases/2022/release-notes-preview)
|
|
||||||
|
|
||||||
## Quickstart: Run a job from a real repository
|
|
||||||
|
|
||||||
If you just want to get from building the sourcecode to using it to execute an action, you will need:
|
|
||||||
|
|
||||||
- The url of your repository
|
|
||||||
- A runner registration token. You can find it at `https://github.com/{your-repo}/settings/actions/runners/new`
|
|
||||||
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone https://github.com/actions/runner
|
|
||||||
cd runner/src
|
|
||||||
./dev.(sh/cmd) layout # the runner that built from source is in {root}/_layout
|
|
||||||
cd ../_layout
|
|
||||||
./config.(sh/cmd) --url https://github.com/{your-repo} --token ABCABCABCABCABCABCABCABCABCAB # accept default name, labels and work folder
|
|
||||||
./run.(sh/cmd)
|
|
||||||
```
|
|
||||||
|
|
||||||
If you trigger a job now, you can see the runner execute it.
|
|
||||||
|
|
||||||
Tip: Make sure your job can run on this runner. The easiest way is to set `runs-on: self-hosted` in the workflow file.
|
|
||||||
|
|
||||||
|
|
||||||
## Development Life Cycle
|
|
||||||
If you're using VS Code, you can follow [these](contribute/vscode.md) steps instead.
|
|
||||||
|
|
||||||
### To Build, Test, Layout
|
|
||||||
|
|
||||||
Navigate to the `src` directory and run the following command:
|
Navigate to the `src` directory and run the following command:
|
||||||
|
|
||||||
@@ -68,7 +39,7 @@ Navigate to the `src` directory and run the following command:
|
|||||||
* `build` (`b`): Build everything and update runner layout folder
|
* `build` (`b`): Build everything and update runner layout folder
|
||||||
* `test` (`t`): Build runner binaries and run unit tests
|
* `test` (`t`): Build runner binaries and run unit tests
|
||||||
|
|
||||||
### Sample developer flow:
|
Sample developer flow:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/actions/runner
|
git clone https://github.com/actions/runner
|
||||||
@@ -80,89 +51,25 @@ cd ./src
|
|||||||
./dev.(sh/cmd) test # run all unit tests before git commit/push
|
./dev.(sh/cmd) test # run all unit tests before git commit/push
|
||||||
```
|
```
|
||||||
|
|
||||||
Let's break that down.
|
View logs:
|
||||||
|
|
||||||
### Clone repository:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone https://github.com/actions/runner
|
|
||||||
cd runner
|
|
||||||
```
|
|
||||||
If you want to push your changes to a remote, it is recommended you fork the repository and use that fork as your origin instead of `https://github.com/actions/runner`.
|
|
||||||
|
|
||||||
|
|
||||||
### Build Layout:
|
|
||||||
|
|
||||||
This command will build all projects, then copies them and other dependencies into a folder called `_layout`. The binaries in this folder are then used for running, debugging the runner.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd ./src # execute the script from this folder
|
|
||||||
./dev.(sh/cmd) layout # the runner that built from source is in {root}/_layout
|
|
||||||
```
|
|
||||||
|
|
||||||
If you make code changes after this point, use the argument `build` to build your code in the `src` folder to keep your `_layout` folder up to date.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd ./src
|
|
||||||
./dev.(sh/cmd) build # {root}/_layout will get updated
|
|
||||||
```
|
|
||||||
### Test Layout:
|
|
||||||
|
|
||||||
This command runs the suite of unit tests in the project
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd ./src
|
|
||||||
./dev.(sh/cmd) test # run all unit tests before git commit/push
|
|
||||||
```
|
|
||||||
|
|
||||||
### Configure Runner:
|
|
||||||
|
|
||||||
If you want to manually test your runner and run actions from a real repository, you'll have to configure it before running it.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd runner/_layout
|
|
||||||
./config.(sh/cmd) # configure your custom runner
|
|
||||||
```
|
|
||||||
|
|
||||||
You will need your the name of your repository and a runner registration token.
|
|
||||||
Check [Quickstart](##Quickstart:-Run-a-job-from-a-real-repository) if you don't know how to get this token.
|
|
||||||
|
|
||||||
These can also be passed down as arguments to `config.(sh/cmd)`:
|
|
||||||
```bash
|
|
||||||
cd runner/_layout
|
|
||||||
./config.(sh/cmd) --url https://github.com/{your-repo} --token ABCABCABCABCABCABCABCABCABCAB
|
|
||||||
```
|
|
||||||
|
|
||||||
### Run Runner
|
|
||||||
|
|
||||||
All that's left to do is to start the runner:
|
|
||||||
```bash
|
|
||||||
cd runner/_layout
|
|
||||||
./run.(sh/cmd) # run your custom runner
|
|
||||||
```
|
|
||||||
|
|
||||||
### View logs:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd runner/_layout/_diag
|
cd runner/_layout/_diag
|
||||||
ls
|
ls
|
||||||
cat (Runner/Worker)_TIMESTAMP.log # view your log file
|
cat (Runner/Worker)_TIMESTAMP.log # view your log file
|
||||||
```
|
```
|
||||||
|
|
||||||
## Editors
|
Run Runner:
|
||||||
|
```bash
|
||||||
|
cd runner/_layout
|
||||||
|
./run.sh # run your custom runner
|
||||||
|
```
|
||||||
|
|
||||||
|
### Editors
|
||||||
|
|
||||||
[Using Visual Studio Code](https://code.visualstudio.com/)
|
[Using Visual Studio Code](https://code.visualstudio.com/)
|
||||||
[Using Visual Studio](https://code.visualstudio.com/docs)
|
[Using Visual Studio](https://code.visualstudio.com/docs)
|
||||||
|
|
||||||
## Styling
|
### Styling
|
||||||
|
|
||||||
We use the .NET Foundation and CoreCLR style guidelines [located here](
|
We use the .NET Foundation and CoreCLR style guidelines [located here](
|
||||||
https://github.com/dotnet/runtime/blob/main/docs/coding-guidelines/coding-style.md)
|
https://github.com/dotnet/corefx/blob/master/Documentation/coding-guidelines/coding-style.md)
|
||||||
|
|
||||||
### Format C# Code
|
|
||||||
|
|
||||||
To format both staged and unstaged .cs files
|
|
||||||
```
|
|
||||||
cd ./src
|
|
||||||
./dev.(cmd|sh) format
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
# Development Life Cycle using VS Code:
|
|
||||||
|
|
||||||
These examples use VS Code, but the idea should be similar across all IDEs as long as you attach to the same processes in the right folder.
|
|
||||||
## Configure
|
|
||||||
|
|
||||||
To successfully start the runner, you need to register it using a repository and a runner registration token.
|
|
||||||
Run `Configure` first to build the source code and set up the runner in `_layout`.
|
|
||||||
Once it's done creating `_layout`, it asks for the url of your repository and your token in the terminal.
|
|
||||||
|
|
||||||
Check [Quickstart](../contribute.md#quickstart-run-a-job-from-a-real-repository) if you don't know how to get this token.
|
|
||||||
|
|
||||||
## Debugging
|
|
||||||
|
|
||||||
Debugging the full lifecycle of a job can be tricky, because there are multiple processes involved.
|
|
||||||
All the configs below can be found in `.vscode/launch.json`.
|
|
||||||
|
|
||||||
## Debug the Listener
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"name": "Run [build]",
|
|
||||||
"type": "coreclr",
|
|
||||||
"request": "launch",
|
|
||||||
"preLaunchTask": "build runner layout", // use the config called "Run" to launch without rebuild
|
|
||||||
"program": "${workspaceFolder}/_layout/bin/Runner.Listener",
|
|
||||||
"args": [
|
|
||||||
"run" // run without args to print usage
|
|
||||||
],
|
|
||||||
"cwd": "${workspaceFolder}/src",
|
|
||||||
"console": "integratedTerminal",
|
|
||||||
"requireExactSource": false,
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
If you launch `Run` or `Run [build]`, it starts a process called `Runner.Listener`.
|
|
||||||
This process will receive any job queued on this repository if the job runs on matching labels (e.g `runs-on: self-hosted`).
|
|
||||||
Once a job is received, a `Runner.Listener` starts a new process of `Runner.Worker`.
|
|
||||||
Since this is a different process, you can't use the same debugger session debug it.
|
|
||||||
Instead, a parallel debugging session has to be started, using a different launch config.
|
|
||||||
Luckily, VS Code supports multiple parallel debugging sessions.
|
|
||||||
|
|
||||||
## Debug the Worker
|
|
||||||
|
|
||||||
Because the worker process is usually started by the listener instead of an IDE, debugging it from start to finish can be tricky.
|
|
||||||
For this reason, `Runner.Worker` can be configured to wait for a debugger to be attached before it begins any actual work.
|
|
||||||
|
|
||||||
Set the environment variable `GITHUB_ACTIONS_RUNNER_ATTACH_DEBUGGER` to `true` or `1` to enable this wait.
|
|
||||||
All worker processes now will wait 20 seconds before they start working on their task.
|
|
||||||
|
|
||||||
This gives enough time to attach a debugger by running `Debug Worker`.
|
|
||||||
If for some reason you have multiple workers running, run the launch config `Attach` instead.
|
|
||||||
Select `Runner.Worker` from the running processes when VS Code prompts for it.
|
|
||||||
@@ -1,217 +0,0 @@
|
|||||||
# Runner Dependency Management Process
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
This document outlines the automated dependency management process for the GitHub Actions Runner, designed to ensure we maintain up-to-date and secure dependencies while providing predictable release cycles.
|
|
||||||
|
|
||||||
## Release Schedule
|
|
||||||
|
|
||||||
- **Monthly Runner Releases**: New runner versions are released monthly
|
|
||||||
- **Weekly Dependency Checks**: Automated workflows check for dependency updates every Monday
|
|
||||||
- **Security Patches**: Critical security vulnerabilities are addressed immediately outside the regular schedule
|
|
||||||
|
|
||||||
## Automated Workflows
|
|
||||||
|
|
||||||
**Note**: These workflows are implemented across separate PRs for easier review and independent deployment. Each workflow includes comprehensive error handling and security-focused vulnerability detection.
|
|
||||||
|
|
||||||
### 1. Foundation Labels
|
|
||||||
|
|
||||||
- **Workflow**: `.github/workflows/setup-labels.yml` (PR #4024)
|
|
||||||
- **Purpose**: Creates consistent dependency labels for all automation workflows
|
|
||||||
- **Labels**: `dependencies`, `security`, `typescript`, `needs-manual-review`
|
|
||||||
- **Prerequisite**: Must be merged before other workflows for proper labeling
|
|
||||||
|
|
||||||
### 2. Node.js Version Updates
|
|
||||||
|
|
||||||
- **Workflow**: `.github/workflows/node-upgrade.yml`
|
|
||||||
- **Schedule**: Mondays at 6:00 AM UTC
|
|
||||||
- **Purpose**: Updates Node.js 20 and 24 versions in `src/Misc/externals.sh`
|
|
||||||
- **Source**: [nodejs.org](https://nodejs.org) and [actions/alpine_nodejs](https://github.com/actions/alpine_nodejs)
|
|
||||||
- **Priority**: First (NPM depends on current Node.js versions)
|
|
||||||
|
|
||||||
### 3. NPM Security Audit
|
|
||||||
|
|
||||||
- **Primary Workflow**: `.github/workflows/npm-audit.yml` ("NPM Audit Fix")
|
|
||||||
- **Schedule**: Mondays at 7:00 AM UTC
|
|
||||||
- **Purpose**: Automated security vulnerability detection and basic fixes
|
|
||||||
- **Location**: `src/Misc/expressionFunc/hashFiles/`
|
|
||||||
- **Features**: npm audit, security patch application, PR creation
|
|
||||||
- **Dependency**: Runs after Node.js updates for optimal compatibility
|
|
||||||
|
|
||||||
- **Fallback Workflow**: `.github/workflows/npm-audit-typescript.yml` ("NPM Audit Fix with TypeScript Auto-Fix")
|
|
||||||
- **Trigger**: Manual dispatch only
|
|
||||||
- **Purpose**: Manual security audit with TypeScript compatibility fixes
|
|
||||||
- **Use Case**: When scheduled workflow fails or needs custom intervention
|
|
||||||
- **Features**: Enhanced TypeScript auto-repair, graduated security response
|
|
||||||
- **How to Use**:
|
|
||||||
1. If the scheduled "NPM Audit Fix" workflow fails, go to Actions tab
|
|
||||||
2. Select "NPM Audit Fix with TypeScript Auto-Fix" workflow
|
|
||||||
3. Click "Run workflow" and optionally specify fix level (auto/manual)
|
|
||||||
4. Review the generated PR for TypeScript compatibility issues
|
|
||||||
|
|
||||||
### 4. .NET SDK Updates
|
|
||||||
|
|
||||||
- **Workflow**: `.github/workflows/dotnet-upgrade.yml`
|
|
||||||
- **Schedule**: Mondays at midnight UTC
|
|
||||||
- **Purpose**: Updates .NET SDK and package versions with build validation
|
|
||||||
- **Features**: Global.json updates, NuGet package management, compatibility checking
|
|
||||||
- **Independence**: Runs independently of Node.js/NPM updates
|
|
||||||
|
|
||||||
### 5. Docker/Buildx Updates
|
|
||||||
|
|
||||||
- **Workflow**: `.github/workflows/docker-buildx-upgrade.yml` ("Docker/Buildx Version Upgrade")
|
|
||||||
- **Schedule**: Mondays at midnight UTC
|
|
||||||
- **Purpose**: Updates Docker and Docker Buildx versions with multi-platform validation
|
|
||||||
- **Features**: Container security scanning, multi-architecture build testing
|
|
||||||
- **Independence**: Runs independently of other dependency updates
|
|
||||||
|
|
||||||
### 6. Dependency Monitoring
|
|
||||||
|
|
||||||
- **Workflow**: `.github/workflows/dependency-check.yml` ("Dependency Status Check")
|
|
||||||
- **Schedule**: Mondays at 11:00 AM UTC
|
|
||||||
- **Purpose**: Comprehensive status report of all dependencies with security audit
|
|
||||||
- **Features**: Multi-dependency checking, npm audit status, build validation, choice of specific component checks
|
|
||||||
- **Summary**: Runs last to capture results from all morning dependency updates
|
|
||||||
|
|
||||||
## Release Process Integration
|
|
||||||
|
|
||||||
### Pre-Release Checklist
|
|
||||||
|
|
||||||
Before each monthly runner release:
|
|
||||||
|
|
||||||
1. **Check Dependency PRs**:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# List all open dependency PRs
|
|
||||||
gh pr list --label "dependencies" --state open
|
|
||||||
|
|
||||||
# List only automated weekly dependency updates
|
|
||||||
gh pr list --label "dependencies-weekly-check" --state open
|
|
||||||
|
|
||||||
# List only custom dependency automation (not dependabot)
|
|
||||||
gh pr list --label "dependencies-not-dependabot" --state open
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Run Manual Dependency Check**:
|
|
||||||
- Go to Actions tab → "Dependency Status Check" → "Run workflow"
|
|
||||||
- Review the summary for any outdated dependencies
|
|
||||||
|
|
||||||
3. **Review and Merge Updates**:
|
|
||||||
- Prioritize security-related updates
|
|
||||||
- Test dependency updates in development environment
|
|
||||||
- Merge approved dependency PRs
|
|
||||||
|
|
||||||
### Vulnerability Response
|
|
||||||
|
|
||||||
#### Critical Security Vulnerabilities
|
|
||||||
|
|
||||||
- **Response Time**: Within 24 hours
|
|
||||||
- **Process**:
|
|
||||||
1. Assess impact on runner security
|
|
||||||
2. Create hotfix branch if runner data security is affected
|
|
||||||
3. Expedite patch release if necessary
|
|
||||||
4. Document in security advisory if applicable
|
|
||||||
|
|
||||||
#### Non-Critical Vulnerabilities
|
|
||||||
|
|
||||||
- **Response Time**: Next monthly release
|
|
||||||
- **Process**:
|
|
||||||
1. Evaluate if vulnerability affects runner functionality
|
|
||||||
2. Include fix in regular dependency update cycle
|
|
||||||
3. Document in release notes
|
|
||||||
|
|
||||||
## Monitoring and Alerts
|
|
||||||
|
|
||||||
### GitHub Actions Workflow Status
|
|
||||||
|
|
||||||
- All dependency workflows create PRs with the `dependencies` label
|
|
||||||
- Failed workflows should be investigated immediately
|
|
||||||
- Weekly dependency status reports are generated automatically
|
|
||||||
|
|
||||||
### Manual Checks
|
|
||||||
|
|
||||||
You can manually trigger dependency checks:
|
|
||||||
|
|
||||||
- **Full Status**: Run "Dependency Status Check" workflow
|
|
||||||
- **Specific Component**: Use the dropdown to check individual dependencies
|
|
||||||
|
|
||||||
## Dependency Labels
|
|
||||||
|
|
||||||
All automated dependency PRs are tagged with labels for easy filtering and management:
|
|
||||||
|
|
||||||
### Primary Labels
|
|
||||||
|
|
||||||
- **`dependencies`**: All automated dependency-related PRs
|
|
||||||
- **`dependencies-weekly-check`**: Automated weekly dependency updates from scheduled workflows
|
|
||||||
- **`dependencies-not-dependabot`**: Custom dependency automation (not created by dependabot)
|
|
||||||
- **`security`**: Security vulnerability fixes and patches
|
|
||||||
- **`typescript`**: TypeScript compatibility and type definition updates
|
|
||||||
- **`needs-manual-review`**: Complex updates requiring human verification
|
|
||||||
|
|
||||||
### Technology-Specific Labels
|
|
||||||
|
|
||||||
- **`node`**: Node.js version updates
|
|
||||||
- **`javascript`**: JavaScript runtime and tooling updates
|
|
||||||
- **`npm`**: NPM package and security updates
|
|
||||||
- **`dotnet`**: .NET SDK and NuGet package updates
|
|
||||||
- **`docker`**: Docker and container tooling updates
|
|
||||||
|
|
||||||
### Workflow-Specific Branches
|
|
||||||
|
|
||||||
- **Node.js updates**: `chore/update-node` branch
|
|
||||||
- **NPM security fixes**: `chore/npm-audit-fix-YYYYMMDD` and `chore/npm-audit-fix-with-ts-repair` branches
|
|
||||||
- **NuGet/.NET updates**: `feature/dotnetsdk-upgrade/{version}` branches
|
|
||||||
- **Docker updates**: `feature/docker-buildx-upgrade` branch
|
|
||||||
|
|
||||||
## Special Considerations
|
|
||||||
|
|
||||||
### Node.js Updates
|
|
||||||
|
|
||||||
When updating Node.js versions, remember to:
|
|
||||||
|
|
||||||
1. Create a corresponding release in [actions/alpine_nodejs](https://github.com/actions/alpine_nodejs)
|
|
||||||
2. Follow the alpine_nodejs getting started guide
|
|
||||||
3. Test container builds with new Node versions
|
|
||||||
|
|
||||||
### .NET SDK Updates
|
|
||||||
|
|
||||||
- Only patch versions are auto-updated within the same major.minor version
|
|
||||||
- Major/minor version updates require manual review and testing
|
|
||||||
|
|
||||||
### Docker Updates
|
|
||||||
|
|
||||||
- Updates include both Docker Engine and Docker Buildx
|
|
||||||
- Verify compatibility with runner container workflows
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Common Issues
|
|
||||||
|
|
||||||
1. **NPM Audit Workflow Fails**:
|
|
||||||
- Check if `package.json` exists in `src/Misc/expressionFunc/hashFiles/`
|
|
||||||
- Verify Node.js setup step succeeded
|
|
||||||
|
|
||||||
2. **Version Detection Fails**:
|
|
||||||
- Check if upstream APIs are available
|
|
||||||
- Verify parsing logic for version extraction
|
|
||||||
|
|
||||||
3. **PR Creation Fails**:
|
|
||||||
- Ensure `GITHUB_TOKEN` has sufficient permissions
|
|
||||||
- Check if branch already exists
|
|
||||||
|
|
||||||
### Contact
|
|
||||||
|
|
||||||
For questions about the dependency management process:
|
|
||||||
|
|
||||||
- Create an issue with the `dependencies` label
|
|
||||||
- Review existing dependency management workflows
|
|
||||||
- Consult the runner team for security-related concerns
|
|
||||||
|
|
||||||
## Metrics and KPIs
|
|
||||||
|
|
||||||
Track these metrics to measure dependency management effectiveness:
|
|
||||||
|
|
||||||
- Number of open dependency PRs at release time
|
|
||||||
- Time to merge dependency updates
|
|
||||||
- Number of security vulnerabilities by severity
|
|
||||||
- Release cycle adherence (monthly target)
|
|
||||||
@@ -58,4 +58,4 @@ Authentication in a workflow run to github.com can be accomplished by using the
|
|||||||
|
|
||||||
Hosted runner authentication differs from self-hosted authentication in that runners do not undergo a registration process, but instead, the hosted runners get the OAuth token directly by reading the `.credentials` file. The scope of this particular token is limited for a given workflow job execution, and the token is revoked as soon as the job is finished.
|
Hosted runner authentication differs from self-hosted authentication in that runners do not undergo a registration process, but instead, the hosted runners get the OAuth token directly by reading the `.credentials` file. The scope of this particular token is limited for a given workflow job execution, and the token is revoked as soon as the job is finished.
|
||||||
|
|
||||||

|

|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 138 KiB After Width: | Height: | Size: 158 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 14 MiB |
@@ -4,7 +4,16 @@
|
|||||||
|
|
||||||
## Supported Distributions and Versions
|
## Supported Distributions and Versions
|
||||||
|
|
||||||
Please see "[Supported architectures and operating systems for self-hosted runners](https://docs.github.com/en/actions/reference/runners/self-hosted-runners#linux)."
|
x64
|
||||||
|
- Red Hat Enterprise Linux 7
|
||||||
|
- CentOS 7
|
||||||
|
- Oracle Linux 7
|
||||||
|
- Fedora 29+
|
||||||
|
- Debian 9+
|
||||||
|
- Ubuntu 16.04+
|
||||||
|
- Linux Mint 18+
|
||||||
|
- openSUSE 15+
|
||||||
|
- SUSE Enterprise Linux (SLES) 12 SP2+
|
||||||
|
|
||||||
## Install .Net Core 3.x Linux Dependencies
|
## Install .Net Core 3.x Linux Dependencies
|
||||||
|
|
||||||
@@ -14,27 +23,27 @@ You might see something like this which indicate a dependency's missing.
|
|||||||
./config.sh
|
./config.sh
|
||||||
libunwind.so.8 => not found
|
libunwind.so.8 => not found
|
||||||
libunwind-x86_64.so.8 => not found
|
libunwind-x86_64.so.8 => not found
|
||||||
Dependencies is missing for Dotnet Core 6.0
|
Dependencies is missing for Dotnet Core 3.0
|
||||||
Execute ./bin/installdependencies.sh to install any missing Dotnet Core 6.0 dependencies.
|
Execute ./bin/installdependencies.sh to install any missing Dotnet Core 3.0 dependencies.
|
||||||
```
|
```
|
||||||
You can easily correct the problem by executing `./bin/installdependencies.sh`.
|
You can easily correct the problem by executing `./bin/installdependencies.sh`.
|
||||||
The `installdependencies.sh` script should install all required dependencies on all supported Linux versions
|
The `installdependencies.sh` script should install all required dependencies on all supported Linux versions
|
||||||
> Note: The `installdependencies.sh` script will try to use the default package management mechanism on your Linux flavor (ex. `yum`/`apt-get`/`apt`).
|
> Note: The `installdependencies.sh` script will try to use the default package management mechanism on your Linux flavor (ex. `yum`/`apt-get`/`apt`).
|
||||||
|
|
||||||
### Full dependencies list
|
### Full dependencies list
|
||||||
|
|
||||||
Debian based OS (Debian, Ubuntu, Linux Mint)
|
Debian based OS (Debian, Ubuntu, Linux Mint)
|
||||||
|
|
||||||
- liblttng-ust1 or liblttng-ust0
|
- liblttng-ust0
|
||||||
- libkrb5-3
|
- libkrb5-3
|
||||||
- zlib1g
|
- zlib1g
|
||||||
- libssl1.1, libssl1.0.2 or libssl1.0.0
|
- libssl1.1, libssl1.0.2 or libssl1.0.0
|
||||||
- libicu63, libicu60, libicu57 or libicu55
|
- libicu63, libicu60, libicu57 or libicu55
|
||||||
|
|
||||||
Fedora based OS (Fedora, Red Hat Enterprise Linux, CentOS, Oracle Linux 7)
|
Fedora based OS (Fedora, Red Hat Enterprise Linux, CentOS, Oracle Linux 7)
|
||||||
|
|
||||||
- lttng-ust
|
- lttng-ust
|
||||||
- openssl-libs
|
- openssl-libs
|
||||||
- krb5-libs
|
- krb5-libs
|
||||||
- zlib
|
- zlib
|
||||||
- libicu
|
- libicu
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
## Supported Versions
|
## Supported Versions
|
||||||
|
|
||||||
Please see "[Supported architectures and operating systems for self-hosted runners](https://docs.github.com/en/actions/reference/runners/self-hosted-runners#macos)."
|
- macOS High Sierra (10.13) and later versions
|
||||||
|
|
||||||
|
|
||||||
## [More .Net Core Prerequisites Information](https://docs.microsoft.com/en-us/dotnet/core/macos-prerequisites?tabs=netcore30)
|
## [More .Net Core Prerequisites Information](https://docs.microsoft.com/en-us/dotnet/core/macos-prerequisites?tabs=netcore30)
|
||||||
|
|||||||
@@ -2,6 +2,11 @@
|
|||||||
|
|
||||||
## Supported Versions
|
## Supported Versions
|
||||||
|
|
||||||
Please see "[Supported architectures and operating systems for self-hosted runners](https://docs.github.com/en/actions/reference/runners/self-hosted-runners#windows)."
|
- Windows 7 64-bit
|
||||||
|
- Windows 8.1 64-bit
|
||||||
|
- Windows 10 64-bit
|
||||||
|
- Windows Server 2012 R2 64-bit
|
||||||
|
- Windows Server 2016 64-bit
|
||||||
|
- Windows Server 2019 64-bit
|
||||||
|
|
||||||
## [More .NET Core Prerequisites Information](https://docs.microsoft.com/en-us/dotnet/core/windows-prerequisites?tabs=netcore30)
|
## [More .NET Core Prerequisites Information](https://docs.microsoft.com/en-us/dotnet/core/windows-prerequisites?tabs=netcore30)
|
||||||
|
|||||||
@@ -1,72 +0,0 @@
|
|||||||
# Source: https://github.com/dotnet/dotnet-docker
|
|
||||||
FROM mcr.microsoft.com/dotnet/runtime-deps:8.0-jammy AS build
|
|
||||||
|
|
||||||
ARG TARGETOS
|
|
||||||
ARG TARGETARCH
|
|
||||||
ARG RUNNER_VERSION
|
|
||||||
ARG RUNNER_CONTAINER_HOOKS_VERSION=0.7.0
|
|
||||||
ARG DOCKER_VERSION=29.0.1
|
|
||||||
ARG BUILDX_VERSION=0.30.0
|
|
||||||
|
|
||||||
RUN apt update -y && apt install curl unzip -y
|
|
||||||
|
|
||||||
WORKDIR /actions-runner
|
|
||||||
RUN export RUNNER_ARCH=${TARGETARCH} \
|
|
||||||
&& if [ "$RUNNER_ARCH" = "amd64" ]; then export RUNNER_ARCH=x64 ; fi \
|
|
||||||
&& curl -f -L -o runner.tar.gz https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-${TARGETOS}-${RUNNER_ARCH}-${RUNNER_VERSION}.tar.gz \
|
|
||||||
&& tar xzf ./runner.tar.gz \
|
|
||||||
&& rm runner.tar.gz
|
|
||||||
|
|
||||||
RUN curl -f -L -o runner-container-hooks.zip https://github.com/actions/runner-container-hooks/releases/download/v${RUNNER_CONTAINER_HOOKS_VERSION}/actions-runner-hooks-k8s-${RUNNER_CONTAINER_HOOKS_VERSION}.zip \
|
|
||||||
&& unzip ./runner-container-hooks.zip -d ./k8s \
|
|
||||||
&& rm runner-container-hooks.zip
|
|
||||||
|
|
||||||
RUN curl -f -L -o runner-container-hooks.zip https://github.com/actions/runner-container-hooks/releases/download/v0.8.0/actions-runner-hooks-k8s-0.8.0.zip \
|
|
||||||
&& unzip ./runner-container-hooks.zip -d ./k8s-novolume \
|
|
||||||
&& rm runner-container-hooks.zip
|
|
||||||
|
|
||||||
RUN export RUNNER_ARCH=${TARGETARCH} \
|
|
||||||
&& if [ "$RUNNER_ARCH" = "amd64" ]; then export DOCKER_ARCH=x86_64 ; fi \
|
|
||||||
&& if [ "$RUNNER_ARCH" = "arm64" ]; then export DOCKER_ARCH=aarch64 ; fi \
|
|
||||||
&& curl -fLo docker.tgz https://download.docker.com/${TARGETOS}/static/stable/${DOCKER_ARCH}/docker-${DOCKER_VERSION}.tgz \
|
|
||||||
&& tar zxvf docker.tgz \
|
|
||||||
&& rm -rf docker.tgz \
|
|
||||||
&& mkdir -p /usr/local/lib/docker/cli-plugins \
|
|
||||||
&& curl -fLo /usr/local/lib/docker/cli-plugins/docker-buildx \
|
|
||||||
"https://github.com/docker/buildx/releases/download/v${BUILDX_VERSION}/buildx-v${BUILDX_VERSION}.linux-${TARGETARCH}" \
|
|
||||||
&& chmod +x /usr/local/lib/docker/cli-plugins/docker-buildx
|
|
||||||
|
|
||||||
FROM mcr.microsoft.com/dotnet/runtime-deps:8.0-jammy
|
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
|
||||||
ENV RUNNER_MANUALLY_TRAP_SIG=1
|
|
||||||
ENV ACTIONS_RUNNER_PRINT_LOG_TO_STDOUT=1
|
|
||||||
ENV ImageOS=ubuntu22
|
|
||||||
|
|
||||||
# 'gpg-agent' and 'software-properties-common' are needed for the 'add-apt-repository' command that follows
|
|
||||||
RUN apt update -y \
|
|
||||||
&& apt install -y --no-install-recommends sudo lsb-release gpg-agent software-properties-common curl jq unzip \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Configure git-core/ppa based on guidance here: https://git-scm.com/download/linux
|
|
||||||
RUN add-apt-repository ppa:git-core/ppa \
|
|
||||||
&& apt update -y \
|
|
||||||
&& apt install -y git \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
WORKDIR /home/runner
|
|
||||||
|
|
||||||
RUN adduser --disabled-password --gecos "" --uid 1001 runner \
|
|
||||||
&& groupadd docker --gid 123 \
|
|
||||||
&& usermod -aG sudo runner \
|
|
||||||
&& usermod -aG docker runner \
|
|
||||||
&& echo "%sudo ALL=(ALL:ALL) NOPASSWD:ALL" > /etc/sudoers \
|
|
||||||
&& echo "Defaults env_keep += \"DEBIAN_FRONTEND\"" >> /etc/sudoers \
|
|
||||||
&& chmod 777 /home/runner
|
|
||||||
|
|
||||||
COPY --chown=runner:docker --from=build /actions-runner .
|
|
||||||
COPY --from=build /usr/local/lib/docker/cli-plugins/docker-buildx /usr/local/lib/docker/cli-plugins/docker-buildx
|
|
||||||
|
|
||||||
RUN install -o root -g root -m 755 docker/* /usr/bin/ && rm -rf docker
|
|
||||||
|
|
||||||
USER runner
|
|
||||||
@@ -1,70 +1,29 @@
|
|||||||
## What's Changed
|
## Features
|
||||||
* Custom Image: Preflight checks by @lawrencegripper in https://github.com/actions/runner/pull/4081
|
- Allow registry credentials for job/service containers (#694)
|
||||||
* Update dotnet sdk to latest version @8.0.415 by @github-actions[bot] in https://github.com/actions/runner/pull/4080
|
|
||||||
* Link to an extant discussion category by @jsoref in https://github.com/actions/runner/pull/4084
|
|
||||||
* Improve logic around decide IsHostedServer. by @TingluoHuang in https://github.com/actions/runner/pull/4086
|
|
||||||
* chore: update Node versions by @github-actions[bot] in https://github.com/actions/runner/pull/4093
|
|
||||||
* Compare updated template evaluator by @ericsciple in https://github.com/actions/runner/pull/4092
|
|
||||||
* fix(dockerfile): set more lenient permissions on /home/runner by @caxu-rh in https://github.com/actions/runner/pull/4083
|
|
||||||
* Add support for libicu73-76 for newer Debian/Ubuntu versions by @lets-build-an-ocean in https://github.com/actions/runner/pull/4098
|
|
||||||
* Bump actions/download-artifact from 5 to 6 by @dependabot[bot] in https://github.com/actions/runner/pull/4089
|
|
||||||
* Bump actions/upload-artifact from 4 to 5 by @dependabot[bot] in https://github.com/actions/runner/pull/4088
|
|
||||||
* Bump Azure.Storage.Blobs from 12.25.1 to 12.26.0 by @dependabot[bot] in https://github.com/actions/runner/pull/4077
|
|
||||||
* Only start runner after network is online by @dupondje in https://github.com/actions/runner/pull/4094
|
|
||||||
* Retry http error related to DNS resolution failure. by @TingluoHuang in https://github.com/actions/runner/pull/4110
|
|
||||||
* Update Docker to v29.0.1 and Buildx to v0.30.0 by @github-actions[bot] in https://github.com/actions/runner/pull/4114
|
|
||||||
* chore: update Node versions by @github-actions[bot] in https://github.com/actions/runner/pull/4115
|
|
||||||
* Update dotnet sdk to latest version @8.0.416 by @github-actions[bot] in https://github.com/actions/runner/pull/4116
|
|
||||||
* Compare updated workflow parser for ActionManifestManager by @ericsciple in https://github.com/actions/runner/pull/4111
|
|
||||||
* Bump npm pkg version for hashFiles. by @TingluoHuang in https://github.com/actions/runner/pull/4122
|
|
||||||
|
|
||||||
## New Contributors
|
## Bugs
|
||||||
* @lawrencegripper made their first contribution in https://github.com/actions/runner/pull/4081
|
- N/A
|
||||||
* @caxu-rh made their first contribution in https://github.com/actions/runner/pull/4083
|
|
||||||
* @lets-build-an-ocean made their first contribution in https://github.com/actions/runner/pull/4098
|
|
||||||
* @dupondje made their first contribution in https://github.com/actions/runner/pull/4094
|
|
||||||
|
|
||||||
**Full Changelog**: https://github.com/actions/runner/compare/v2.329.0...v2.330.0
|
## Misc
|
||||||
|
- N/A
|
||||||
_Note: Actions Runner follows a progressive release policy, so the latest release might not be available to your enterprise, organization, or repository yet.
|
|
||||||
To confirm which version of the Actions Runner you should expect, please view the download instructions for your enterprise, organization, or repository.
|
|
||||||
See https://docs.github.com/en/enterprise-cloud@latest/actions/hosting-your-own-runners/adding-self-hosted-runners_
|
|
||||||
|
|
||||||
## Windows x64
|
## Windows x64
|
||||||
|
|
||||||
We recommend configuring the runner in a root folder of the Windows drive (e.g. "C:\actions-runner"). This will help avoid issues related to service identity folder permissions and long file path restrictions on Windows.
|
We recommend configuring the runner in a root folder of the Windows drive (e.g. "C:\actions-runner"). This will help avoid issues related to service identity folder permissions and long file path restrictions on Windows.
|
||||||
|
|
||||||
The following snipped needs to be run on `powershell`:
|
The following snipped needs to be run on `powershell`:
|
||||||
|
``` powershell
|
||||||
```powershell
|
|
||||||
# Create a folder under the drive root
|
# Create a folder under the drive root
|
||||||
mkdir \actions-runner ; cd \actions-runner
|
mkdir \actions-runner ; cd \actions-runner
|
||||||
# Download the latest runner package
|
# Download the latest runner package
|
||||||
Invoke-WebRequest -Uri https://github.com/actions/runner/releases/download/v<RUNNER_VERSION>/actions-runner-win-x64-<RUNNER_VERSION>.zip -OutFile actions-runner-win-x64-<RUNNER_VERSION>.zip
|
Invoke-WebRequest -Uri https://github.com/actions/runner/releases/download/v<RUNNER_VERSION>/actions-runner-win-x64-<RUNNER_VERSION>.zip -OutFile actions-runner-win-x64-<RUNNER_VERSION>.zip
|
||||||
# Extract the installer
|
# Extract the installer
|
||||||
Add-Type -AssemblyName System.IO.Compression.FileSystem ;
|
Add-Type -AssemblyName System.IO.Compression.FileSystem ;
|
||||||
[System.IO.Compression.ZipFile]::ExtractToDirectory("$PWD\actions-runner-win-x64-<RUNNER_VERSION>.zip", "$PWD")
|
[System.IO.Compression.ZipFile]::ExtractToDirectory("$PWD\actions-runner-win-x64-<RUNNER_VERSION>.zip", "$PWD")
|
||||||
```
|
```
|
||||||
|
|
||||||
## Windows arm64
|
## OSX
|
||||||
|
|
||||||
We recommend configuring the runner in a root folder of the Windows drive (e.g. "C:\actions-runner"). This will help avoid issues related to service identity folder permissions and long file path restrictions on Windows.
|
``` bash
|
||||||
|
|
||||||
The following snipped needs to be run on `powershell`:
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
# Create a folder under the drive root
|
|
||||||
mkdir \actions-runner ; cd \actions-runner
|
|
||||||
# Download the latest runner package
|
|
||||||
Invoke-WebRequest -Uri https://github.com/actions/runner/releases/download/v<RUNNER_VERSION>/actions-runner-win-arm64-<RUNNER_VERSION>.zip -OutFile actions-runner-win-arm64-<RUNNER_VERSION>.zip
|
|
||||||
# Extract the installer
|
|
||||||
Add-Type -AssemblyName System.IO.Compression.FileSystem ;
|
|
||||||
[System.IO.Compression.ZipFile]::ExtractToDirectory("$PWD\actions-runner-win-arm64-<RUNNER_VERSION>.zip", "$PWD")
|
|
||||||
```
|
|
||||||
|
|
||||||
## OSX x64
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Create a folder
|
# Create a folder
|
||||||
mkdir actions-runner && cd actions-runner
|
mkdir actions-runner && cd actions-runner
|
||||||
# Download the latest runner package
|
# Download the latest runner package
|
||||||
@@ -73,20 +32,9 @@ curl -O -L https://github.com/actions/runner/releases/download/v<RUNNER_VERSION>
|
|||||||
tar xzf ./actions-runner-osx-x64-<RUNNER_VERSION>.tar.gz
|
tar xzf ./actions-runner-osx-x64-<RUNNER_VERSION>.tar.gz
|
||||||
```
|
```
|
||||||
|
|
||||||
## OSX arm64 (Apple silicon)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Create a folder
|
|
||||||
mkdir actions-runner && cd actions-runner
|
|
||||||
# Download the latest runner package
|
|
||||||
curl -O -L https://github.com/actions/runner/releases/download/v<RUNNER_VERSION>/actions-runner-osx-arm64-<RUNNER_VERSION>.tar.gz
|
|
||||||
# Extract the installer
|
|
||||||
tar xzf ./actions-runner-osx-arm64-<RUNNER_VERSION>.tar.gz
|
|
||||||
```
|
|
||||||
|
|
||||||
## Linux x64
|
## Linux x64
|
||||||
|
|
||||||
```bash
|
``` bash
|
||||||
# Create a folder
|
# Create a folder
|
||||||
mkdir actions-runner && cd actions-runner
|
mkdir actions-runner && cd actions-runner
|
||||||
# Download the latest runner package
|
# Download the latest runner package
|
||||||
@@ -95,9 +43,9 @@ curl -O -L https://github.com/actions/runner/releases/download/v<RUNNER_VERSION>
|
|||||||
tar xzf ./actions-runner-linux-x64-<RUNNER_VERSION>.tar.gz
|
tar xzf ./actions-runner-linux-x64-<RUNNER_VERSION>.tar.gz
|
||||||
```
|
```
|
||||||
|
|
||||||
## Linux arm64
|
## Linux arm64 (Pre-release)
|
||||||
|
|
||||||
```bash
|
``` bash
|
||||||
# Create a folder
|
# Create a folder
|
||||||
mkdir actions-runner && cd actions-runner
|
mkdir actions-runner && cd actions-runner
|
||||||
# Download the latest runner package
|
# Download the latest runner package
|
||||||
@@ -106,9 +54,9 @@ curl -O -L https://github.com/actions/runner/releases/download/v<RUNNER_VERSION>
|
|||||||
tar xzf ./actions-runner-linux-arm64-<RUNNER_VERSION>.tar.gz
|
tar xzf ./actions-runner-linux-arm64-<RUNNER_VERSION>.tar.gz
|
||||||
```
|
```
|
||||||
|
|
||||||
## Linux arm
|
## Linux arm (Pre-release)
|
||||||
|
|
||||||
```bash
|
``` bash
|
||||||
# Create a folder
|
# Create a folder
|
||||||
mkdir actions-runner && cd actions-runner
|
mkdir actions-runner && cd actions-runner
|
||||||
# Download the latest runner package
|
# Download the latest runner package
|
||||||
@@ -118,17 +66,4 @@ tar xzf ./actions-runner-linux-arm-<RUNNER_VERSION>.tar.gz
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Using your self hosted runner
|
## Using your self hosted runner
|
||||||
|
|
||||||
For additional details about configuring, running, or shutting down the runner please check out our [product docs.](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/adding-self-hosted-runners)
|
For additional details about configuring, running, or shutting down the runner please check out our [product docs.](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/adding-self-hosted-runners)
|
||||||
|
|
||||||
## SHA-256 Checksums
|
|
||||||
|
|
||||||
The SHA-256 checksums for the packages included in this build are shown below:
|
|
||||||
|
|
||||||
- actions-runner-win-x64-<RUNNER_VERSION>.zip <!-- BEGIN SHA win-x64 --><WIN_X64_SHA><!-- END SHA win-x64 -->
|
|
||||||
- actions-runner-win-arm64-<RUNNER_VERSION>.zip <!-- BEGIN SHA win-arm64 --><WIN_ARM64_SHA><!-- END SHA win-arm64 -->
|
|
||||||
- actions-runner-osx-x64-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA osx-x64 --><OSX_X64_SHA><!-- END SHA osx-x64 -->
|
|
||||||
- actions-runner-osx-arm64-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA osx-arm64 --><OSX_ARM64_SHA><!-- END SHA osx-arm64 -->
|
|
||||||
- actions-runner-linux-x64-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA linux-x64 --><LINUX_X64_SHA><!-- END SHA linux-x64 -->
|
|
||||||
- actions-runner-linux-arm64-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA linux-arm64 --><LINUX_ARM64_SHA><!-- END SHA linux-arm64 -->
|
|
||||||
- actions-runner-linux-arm-<RUNNER_VERSION>.tar.gz <!-- BEGIN SHA linux-arm --><LINUX_ARM_SHA><!-- END SHA linux-arm -->
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
<Update to ./src/runnerversion when creating release>
|
2.273.4
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# Sample scripts for self-hosted runners
|
# Sample scripts for self-hosted runners
|
||||||
|
|
||||||
Here are some examples to work from if you'd like to automate your use of self-hosted runners.
|
Here are some examples to work from if you'd like to automate your use of self-hosted runners.
|
||||||
See the docs [here](../docs/automate.md).
|
See the docs [here](../docs/automate.md).
|
||||||
@@ -2,81 +2,34 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
#
|
||||||
|
# Downloads latest releases (not pre-release) runner
|
||||||
|
# Configures as a service
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
# RUNNER_CFG_PAT=<yourPAT> ./create-latest-svc.sh myuser/myrepo my.ghe.deployment.net
|
||||||
|
# RUNNER_CFG_PAT=<yourPAT> ./create-latest-svc.sh myorg my.ghe.deployment.net
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# export RUNNER_CFG_PAT=<yourPAT>
|
||||||
|
# ./create-latest-svc scope [ghe_domain] [name] [user]
|
||||||
|
#
|
||||||
|
# scope required repo (:owner/:repo) or org (:organization)
|
||||||
|
# ghe_domain optional the fully qualified domain name of your GitHub Enterprise Server deployment
|
||||||
|
# name optional defaults to hostname
|
||||||
|
# user optional user svc will run as. defaults to current
|
||||||
|
#
|
||||||
# Notes:
|
# Notes:
|
||||||
# PATS over envvars are more secure
|
# PATS over envvars are more secure
|
||||||
# Downloads latest runner release (not pre-release)
|
|
||||||
# Configures it as a service more secure
|
|
||||||
# Should be used on VMs and not containers
|
# Should be used on VMs and not containers
|
||||||
# Works on OSX and Linux
|
# Works on OSX and Linux
|
||||||
# Assumes x64 arch (support arm64)
|
# Assumes x64 arch
|
||||||
# See EXAMPLES below
|
#
|
||||||
|
|
||||||
flags_found=false
|
runner_scope=${1}
|
||||||
|
ghe_hostname=${2}
|
||||||
while getopts 's:g:n:r:u:l:df' opt; do
|
runner_name=${3:-$(hostname)}
|
||||||
flags_found=true
|
svc_user=${4:-$USER}
|
||||||
|
|
||||||
case $opt in
|
|
||||||
s)
|
|
||||||
runner_scope=$OPTARG
|
|
||||||
;;
|
|
||||||
g)
|
|
||||||
ghe_hostname=$OPTARG
|
|
||||||
;;
|
|
||||||
n)
|
|
||||||
runner_name=$OPTARG
|
|
||||||
;;
|
|
||||||
r)
|
|
||||||
runner_group=$OPTARG
|
|
||||||
;;
|
|
||||||
u)
|
|
||||||
svc_user=$OPTARG
|
|
||||||
;;
|
|
||||||
l)
|
|
||||||
labels=$OPTARG
|
|
||||||
;;
|
|
||||||
f)
|
|
||||||
replace='true'
|
|
||||||
;;
|
|
||||||
d)
|
|
||||||
disableupdate='true'
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "
|
|
||||||
Runner Service Installer
|
|
||||||
Examples:
|
|
||||||
RUNNER_CFG_PAT=<yourPAT> ./create-latest-svc.sh myuser/myrepo my.ghe.deployment.net
|
|
||||||
RUNNER_CFG_PAT=<yourPAT> ./create-latest-svc.sh -s myorg -u user_name -l label1,label2
|
|
||||||
Usage:
|
|
||||||
export RUNNER_CFG_PAT=<yourPAT>
|
|
||||||
./create-latest-svc scope [ghe_domain] [name] [user] [labels]
|
|
||||||
-s required scope: repo (:owner/:repo) or org (:organization)
|
|
||||||
-g optional ghe_hostname: the fully qualified domain name of your GitHub Enterprise Server deployment
|
|
||||||
-n optional name of the runner, defaults to hostname
|
|
||||||
-r optional name of the runner group to add the runner to, defaults to the Default group
|
|
||||||
-u optional user svc will run as, defaults to current
|
|
||||||
-l optional list of labels (split by comma) applied on the runner
|
|
||||||
-d optional allow runner to remain on the current version for one month after the release of a newer version
|
|
||||||
-f optional replace any existing runner with the same name"
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
shift "$((OPTIND - 1))"
|
|
||||||
|
|
||||||
if ! "$flags_found"; then
|
|
||||||
runner_scope=${1}
|
|
||||||
ghe_hostname=${2}
|
|
||||||
runner_name=${3:-$(hostname)}
|
|
||||||
svc_user=${4:-$USER}
|
|
||||||
labels=${5}
|
|
||||||
runner_group=${6}
|
|
||||||
fi
|
|
||||||
|
|
||||||
# apply defaults
|
|
||||||
runner_name=${runner_name:-$(hostname)}
|
|
||||||
svc_user=${svc_user:-$USER}
|
|
||||||
|
|
||||||
echo "Configuring runner @ ${runner_scope}"
|
echo "Configuring runner @ ${runner_scope}"
|
||||||
sudo echo
|
sudo echo
|
||||||
@@ -87,9 +40,6 @@ sudo echo
|
|||||||
runner_plat=linux
|
runner_plat=linux
|
||||||
[ ! -z "$(which sw_vers)" ] && runner_plat=osx;
|
[ ! -z "$(which sw_vers)" ] && runner_plat=osx;
|
||||||
|
|
||||||
runner_arch=x64
|
|
||||||
[ ! -z "$(arch | grep arm64)" ] && runner_arch=arm64
|
|
||||||
|
|
||||||
function fatal()
|
function fatal()
|
||||||
{
|
{
|
||||||
echo "error: $1" >&2
|
echo "error: $1" >&2
|
||||||
@@ -142,7 +92,7 @@ echo "Downloading latest runner ..."
|
|||||||
# For the GHES Alpha, download the runner from github.com
|
# For the GHES Alpha, download the runner from github.com
|
||||||
latest_version_label=$(curl -s -X GET 'https://api.github.com/repos/actions/runner/releases/latest' | jq -r '.tag_name')
|
latest_version_label=$(curl -s -X GET 'https://api.github.com/repos/actions/runner/releases/latest' | jq -r '.tag_name')
|
||||||
latest_version=$(echo ${latest_version_label:1})
|
latest_version=$(echo ${latest_version_label:1})
|
||||||
runner_file="actions-runner-${runner_plat}-${runner_arch}-${latest_version}.tar.gz"
|
runner_file="actions-runner-${runner_plat}-x64-${latest_version}.tar.gz"
|
||||||
|
|
||||||
if [ -f "${runner_file}" ]; then
|
if [ -f "${runner_file}" ]; then
|
||||||
echo "${runner_file} exists. skipping download."
|
echo "${runner_file} exists. skipping download."
|
||||||
@@ -180,8 +130,8 @@ fi
|
|||||||
|
|
||||||
echo
|
echo
|
||||||
echo "Configuring ${runner_name} @ $runner_url"
|
echo "Configuring ${runner_name} @ $runner_url"
|
||||||
echo "./config.sh --unattended --url $runner_url --token *** --name $runner_name ${labels:+--labels $labels} ${runner_group:+--runnergroup \"$runner_group\"} ${disableupdate:+--disableupdate}"
|
echo "./config.sh --unattended --url $runner_url --token *** --name $runner_name"
|
||||||
sudo -E -u ${svc_user} ./config.sh --unattended --url $runner_url --token $RUNNER_TOKEN ${replace:+--replace} --name $runner_name ${labels:+--labels $labels} ${runner_group:+--runnergroup "$runner_group"} ${disableupdate:+--disableupdate}
|
sudo -E -u ${svc_user} ./config.sh --unattended --url $runner_url --token $RUNNER_TOKEN --name $runner_name
|
||||||
|
|
||||||
#---------------------------------------
|
#---------------------------------------
|
||||||
# Configuring as a service
|
# Configuring as a service
|
||||||
@@ -190,7 +140,7 @@ echo
|
|||||||
echo "Configuring as a service ..."
|
echo "Configuring as a service ..."
|
||||||
prefix=""
|
prefix=""
|
||||||
if [ "${runner_plat}" == "linux" ]; then
|
if [ "${runner_plat}" == "linux" ]; then
|
||||||
prefix="sudo "
|
prefix="sudo "
|
||||||
fi
|
fi
|
||||||
|
|
||||||
${prefix}./svc.sh install ${svc_user}
|
${prefix}./svc.sh install ${svc_user}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/bash
|
#/bin/bash
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ set -e
|
|||||||
#
|
#
|
||||||
# Usage:
|
# Usage:
|
||||||
# export RUNNER_CFG_PAT=<yourPAT>
|
# export RUNNER_CFG_PAT=<yourPAT>
|
||||||
# ./delete.sh <scope> [<name>]
|
# ./delete.sh scope name
|
||||||
#
|
#
|
||||||
# scope required repo (:owner/:repo) or org (:organization)
|
# scope required repo (:owner/:repo) or org (:organization)
|
||||||
# name optional defaults to hostname. name to delete
|
# name optional defaults to hostname. name to delete
|
||||||
@@ -26,17 +26,17 @@ set -e
|
|||||||
runner_scope=${1}
|
runner_scope=${1}
|
||||||
runner_name=${2}
|
runner_name=${2}
|
||||||
|
|
||||||
function fatal()
|
echo "Deleting runner ${runner_name} @ ${runner_scope}"
|
||||||
|
|
||||||
|
function fatal()
|
||||||
{
|
{
|
||||||
echo "error: $1" >&2
|
echo "error: $1" >&2
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ -z "${runner_scope}" ]; then fatal "supply scope as argument 1"; fi
|
if [ -z "${runner_scope}" ]; then fatal "supply scope as argument 1"; fi
|
||||||
|
if [ -z "${runner_name}" ]; then fatal "supply name as argument 2"; fi
|
||||||
if [ -z "${RUNNER_CFG_PAT}" ]; then fatal "RUNNER_CFG_PAT must be set before calling"; fi
|
if [ -z "${RUNNER_CFG_PAT}" ]; then fatal "RUNNER_CFG_PAT must be set before calling"; fi
|
||||||
if [ -z "${runner_name}" ]; then runner_name=`hostname`; fi
|
|
||||||
|
|
||||||
echo "Deleting runner ${runner_name} @ ${runner_scope}"
|
|
||||||
|
|
||||||
which curl || fatal "curl required. Please install in PATH with apt-get, brew, etc"
|
which curl || fatal "curl required. Please install in PATH with apt-get, brew, etc"
|
||||||
which jq || fatal "jq required. Please install in PATH with apt-get, brew, etc"
|
which jq || fatal "jq required. Please install in PATH with apt-get, brew, etc"
|
||||||
@@ -51,7 +51,7 @@ fi
|
|||||||
# Ensure offline
|
# Ensure offline
|
||||||
#--------------------------------------
|
#--------------------------------------
|
||||||
runner_status=$(curl -s -X GET ${base_api_url}/${runner_scope}/actions/runners?per_page=100 -H "accept: application/vnd.github.everest-preview+json" -H "authorization: token ${RUNNER_CFG_PAT}" \
|
runner_status=$(curl -s -X GET ${base_api_url}/${runner_scope}/actions/runners?per_page=100 -H "accept: application/vnd.github.everest-preview+json" -H "authorization: token ${RUNNER_CFG_PAT}" \
|
||||||
| jq -M -j ".runners | .[] | select(.name == \"${runner_name}\") | .status")
|
| jq -M -j ".runners | .[] | [select(.name == \"${runner_name}\")] | .[0].status")
|
||||||
|
|
||||||
if [ -z "${runner_status}" ]; then
|
if [ -z "${runner_status}" ]; then
|
||||||
fatal "Could not find runner with name ${runner_name}"
|
fatal "Could not find runner with name ${runner_name}"
|
||||||
@@ -67,7 +67,7 @@ fi
|
|||||||
# Get id of runner to remove
|
# Get id of runner to remove
|
||||||
#--------------------------------------
|
#--------------------------------------
|
||||||
runner_id=$(curl -s -X GET ${base_api_url}/${runner_scope}/actions/runners?per_page=100 -H "accept: application/vnd.github.everest-preview+json" -H "authorization: token ${RUNNER_CFG_PAT}" \
|
runner_id=$(curl -s -X GET ${base_api_url}/${runner_scope}/actions/runners?per_page=100 -H "accept: application/vnd.github.everest-preview+json" -H "authorization: token ${RUNNER_CFG_PAT}" \
|
||||||
| jq -M -j ".runners | .[] | select(.name == \"${runner_name}\") | .id")
|
| jq -M -j ".runners | .[] | [select(.name == \"${runner_name}\")] | .[0].id")
|
||||||
|
|
||||||
if [ -z "${runner_id}" ]; then
|
if [ -z "${runner_id}" ]; then
|
||||||
fatal "Could not find runner with name ${runner_name}"
|
fatal "Could not find runner with name ${runner_name}"
|
||||||
|
|||||||
@@ -73,4 +73,4 @@ if [ "${runner_plat}" == "linux" ]; then
|
|||||||
fi
|
fi
|
||||||
${prefix}./svc.sh stop
|
${prefix}./svc.sh stop
|
||||||
${prefix}./svc.sh uninstall
|
${prefix}./svc.sh uninstall
|
||||||
./config.sh remove --token $REMOVE_TOKEN
|
${prefix}./config.sh remove --token $REMOVE_TOKEN
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
[*.cs]
|
|
||||||
charset = utf-8-bom
|
|
||||||
insert_final_newline = true
|
|
||||||
|
|
||||||
csharp_new_line_before_else = true
|
|
||||||
csharp_new_line_before_catch = true
|
|
||||||
csharp_new_line_before_finally = true
|
|
||||||
csharp_new_line_before_open_brace = all
|
|
||||||
|
|
||||||
csharp_space_after_keywords_in_control_flow_statements = true
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio Version 16
|
# Visual Studio Version 16
|
||||||
VisualStudioVersion = 16.0.29411.138
|
VisualStudioVersion = 16.0.29411.138
|
||||||
@@ -21,11 +21,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sdk", "Sdk\Sdk.csproj", "{D
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "Test\Test.csproj", "{C932061F-F6A1-4F1E-B854-A6C6B30DC3EF}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "Test\Test.csproj", "{C932061F-F6A1-4F1E-B854-A6C6B30DC3EF}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{EFB254FC-7927-445E-BA64-6676ADB309E9}"
|
|
||||||
ProjectSection(SolutionItems) = preProject
|
|
||||||
.editorconfig = .editorconfig
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|||||||
@@ -24,16 +24,10 @@
|
|||||||
<PropertyGroup Condition="'$(BUILD_OS)' == 'Windows' AND '$(PackageRuntime)' == 'win-x86'">
|
<PropertyGroup Condition="'$(BUILD_OS)' == 'Windows' AND '$(PackageRuntime)' == 'win-x86'">
|
||||||
<DefineConstants>$(DefineConstants);X86</DefineConstants>
|
<DefineConstants>$(DefineConstants);X86</DefineConstants>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(BUILD_OS)' == 'Windows' AND '$(PackageRuntime)' == 'win-arm64'">
|
|
||||||
<DefineConstants>$(DefineConstants);ARM64</DefineConstants>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(BUILD_OS)' == 'OSX' AND '$(PackageRuntime)' == 'osx-x64'">
|
<PropertyGroup Condition="'$(BUILD_OS)' == 'OSX'">
|
||||||
<DefineConstants>$(DefineConstants);X64</DefineConstants>
|
<DefineConstants>$(DefineConstants);X64</DefineConstants>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(BUILD_OS)' == 'OSX' AND '$(PackageRuntime)' == 'osx-arm64'">
|
|
||||||
<DefineConstants>$(DefineConstants);ARM64</DefineConstants>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(BUILD_OS)' == 'Linux' AND ('$(PackageRuntime)' == 'linux-x64' OR '$(PackageRuntime)' == '')">
|
<PropertyGroup Condition="'$(BUILD_OS)' == 'Linux' AND ('$(PackageRuntime)' == 'linux-x64' OR '$(PackageRuntime)' == '')">
|
||||||
<DefineConstants>$(DefineConstants);X64</DefineConstants>
|
<DefineConstants>$(DefineConstants);X64</DefineConstants>
|
||||||
@@ -57,13 +51,4 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<!-- Enable NuGet package auditing -->
|
|
||||||
<NuGetAudit>true</NuGetAudit>
|
|
||||||
<!-- Audit direct and transitive packages -->
|
|
||||||
<NuGetAuditMode>all</NuGetAuditMode>
|
|
||||||
<!-- Report low, moderate, high and critical advisories -->
|
|
||||||
<NuGetAuditLevel>moderate</NuGetAuditLevel>
|
|
||||||
</PropertyGroup>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
1514
src/Misc/dotnet-install.ps1
vendored
1514
src/Misc/dotnet-install.ps1
vendored
File diff suppressed because it is too large
Load Diff
1381
src/Misc/dotnet-install.sh
vendored
1381
src/Misc/dotnet-install.sh
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"plugins": ["@typescript-eslint", "@stylistic"],
|
"plugins": ["jest", "@typescript-eslint"],
|
||||||
"extends": ["plugin:github/recommended"],
|
"extends": ["plugin:github/es6"],
|
||||||
"parser": "@typescript-eslint/parser",
|
"parser": "@typescript-eslint/parser",
|
||||||
"parserOptions": {
|
"parserOptions": {
|
||||||
"ecmaVersion": 9,
|
"ecmaVersion": 9,
|
||||||
@@ -17,16 +17,13 @@
|
|||||||
"@typescript-eslint/no-require-imports": "error",
|
"@typescript-eslint/no-require-imports": "error",
|
||||||
"@typescript-eslint/array-type": "error",
|
"@typescript-eslint/array-type": "error",
|
||||||
"@typescript-eslint/await-thenable": "error",
|
"@typescript-eslint/await-thenable": "error",
|
||||||
"@typescript-eslint/naming-convention": [
|
"@typescript-eslint/ban-ts-ignore": "error",
|
||||||
"error",
|
|
||||||
{
|
|
||||||
"selector": "default",
|
|
||||||
"format": ["camelCase"]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"camelcase": "off",
|
"camelcase": "off",
|
||||||
|
"@typescript-eslint/camelcase": "error",
|
||||||
|
"@typescript-eslint/class-name-casing": "error",
|
||||||
"@typescript-eslint/explicit-function-return-type": ["error", {"allowExpressions": true}],
|
"@typescript-eslint/explicit-function-return-type": ["error", {"allowExpressions": true}],
|
||||||
"@stylistic/func-call-spacing": ["error", "never"],
|
"@typescript-eslint/func-call-spacing": ["error", "never"],
|
||||||
|
"@typescript-eslint/generic-type-naming": ["error", "^[A-Z][A-Za-z]*$"],
|
||||||
"@typescript-eslint/no-array-constructor": "error",
|
"@typescript-eslint/no-array-constructor": "error",
|
||||||
"@typescript-eslint/no-empty-interface": "error",
|
"@typescript-eslint/no-empty-interface": "error",
|
||||||
"@typescript-eslint/no-explicit-any": "error",
|
"@typescript-eslint/no-explicit-any": "error",
|
||||||
@@ -36,6 +33,7 @@
|
|||||||
"@typescript-eslint/no-misused-new": "error",
|
"@typescript-eslint/no-misused-new": "error",
|
||||||
"@typescript-eslint/no-namespace": "error",
|
"@typescript-eslint/no-namespace": "error",
|
||||||
"@typescript-eslint/no-non-null-assertion": "warn",
|
"@typescript-eslint/no-non-null-assertion": "warn",
|
||||||
|
"@typescript-eslint/no-object-literal-type-assertion": "error",
|
||||||
"@typescript-eslint/no-unnecessary-qualifier": "error",
|
"@typescript-eslint/no-unnecessary-qualifier": "error",
|
||||||
"@typescript-eslint/no-unnecessary-type-assertion": "error",
|
"@typescript-eslint/no-unnecessary-type-assertion": "error",
|
||||||
"@typescript-eslint/no-useless-constructor": "error",
|
"@typescript-eslint/no-useless-constructor": "error",
|
||||||
@@ -43,19 +41,19 @@
|
|||||||
"@typescript-eslint/prefer-for-of": "warn",
|
"@typescript-eslint/prefer-for-of": "warn",
|
||||||
"@typescript-eslint/prefer-function-type": "warn",
|
"@typescript-eslint/prefer-function-type": "warn",
|
||||||
"@typescript-eslint/prefer-includes": "error",
|
"@typescript-eslint/prefer-includes": "error",
|
||||||
|
"@typescript-eslint/prefer-interface": "error",
|
||||||
"@typescript-eslint/prefer-string-starts-ends-with": "error",
|
"@typescript-eslint/prefer-string-starts-ends-with": "error",
|
||||||
"@typescript-eslint/promise-function-async": "error",
|
"@typescript-eslint/promise-function-async": "error",
|
||||||
"@typescript-eslint/require-array-sort-compare": "error",
|
"@typescript-eslint/require-array-sort-compare": "error",
|
||||||
"@typescript-eslint/restrict-plus-operands": "error",
|
"@typescript-eslint/restrict-plus-operands": "error",
|
||||||
"@stylistic/semi": ["error", "never"],
|
"semi": "off",
|
||||||
"@stylistic/type-annotation-spacing": "error",
|
"@typescript-eslint/semi": ["error", "never"],
|
||||||
"@typescript-eslint/unbound-method": "error",
|
"@typescript-eslint/type-annotation-spacing": "error",
|
||||||
"filenames/match-regex" : "off",
|
"@typescript-eslint/unbound-method": "error"
|
||||||
"github/no-then" : 1, // warning
|
|
||||||
"semi": "off"
|
|
||||||
},
|
},
|
||||||
"env": {
|
"env": {
|
||||||
"node": true,
|
"node": true,
|
||||||
"es6": true
|
"es6": true,
|
||||||
|
"jest/globals": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,19 +1,11 @@
|
|||||||
|
|
||||||
{
|
{
|
||||||
"printWidth": 80,
|
"printWidth": 80,
|
||||||
"tabWidth": 2,
|
"tabWidth": 2,
|
||||||
"useTabs": false,
|
"useTabs": false,
|
||||||
"semi": false,
|
"semi": false,
|
||||||
"singleQuote": true,
|
"singleQuote": true,
|
||||||
"trailingComma": "none",
|
"trailingComma": "none",
|
||||||
"bracketSpacing": false,
|
"bracketSpacing": false,
|
||||||
"arrowParens": "avoid",
|
"arrowParens": "avoid",
|
||||||
"overrides": [
|
"parser": "typescript"
|
||||||
{
|
}
|
||||||
"files": "*.{js,ts,json}",
|
|
||||||
"options": {
|
|
||||||
"tabWidth": 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,3 +1 @@
|
|||||||
To compile this package (output will be stored in `Misc/layoutbin`) run `npm install && npm run prepare && npm run all`.
|
To update hashFiles under `Misc/layoutbin` run `npm install && npm run all`
|
||||||
|
|
||||||
When you commit changes to the JSON or Typescript file, the javascript binary will be automatically re-compiled and added to the latest commit.
|
|
||||||
8647
src/Misc/expressionFunc/hashFiles/package-lock.json
generated
8647
src/Misc/expressionFunc/hashFiles/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -9,8 +9,7 @@
|
|||||||
"format-check": "prettier --check **/*.ts",
|
"format-check": "prettier --check **/*.ts",
|
||||||
"lint": "eslint src/**/*.ts",
|
"lint": "eslint src/**/*.ts",
|
||||||
"pack": "ncc build -o ../../layoutbin/hashFiles",
|
"pack": "ncc build -o ../../layoutbin/hashFiles",
|
||||||
"all": "npm run format && npm run lint && npm run build && npm run pack",
|
"all": "npm run build && npm run format && npm run lint && npm run pack"
|
||||||
"prepare": "cd ../../../../ && husky"
|
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -19,33 +18,18 @@
|
|||||||
"keywords": [
|
"keywords": [
|
||||||
"actions"
|
"actions"
|
||||||
],
|
],
|
||||||
"lint-staged": {
|
|
||||||
"*.md": [
|
|
||||||
"prettier --write",
|
|
||||||
"git add ."
|
|
||||||
],
|
|
||||||
"*.{ts,json}": [
|
|
||||||
"sh -c 'npm run all'",
|
|
||||||
"git add ."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"author": "GitHub Actions",
|
"author": "GitHub Actions",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/glob": "^0.4.0"
|
"@actions/glob": "^0.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@stylistic/eslint-plugin": "^3.1.0",
|
"@types/node": "^12.7.12",
|
||||||
"@types/node": "^22.0.0",
|
"@typescript-eslint/parser": "^2.8.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
"@zeit/ncc": "^0.20.5",
|
||||||
"@typescript-eslint/parser": "^8.0.0",
|
"eslint": "^6.8.0",
|
||||||
"@vercel/ncc": "^0.38.3",
|
"eslint-plugin-github": "^2.0.0",
|
||||||
"eslint": "^8.47.0",
|
"prettier": "^1.19.1",
|
||||||
"eslint-plugin-github": "^4.10.2",
|
"typescript": "^3.6.4"
|
||||||
"eslint-plugin-prettier": "^5.0.0",
|
|
||||||
"husky": "^9.1.7",
|
|
||||||
"lint-staged": "^15.5.0",
|
|
||||||
"prettier": "^3.0.3",
|
|
||||||
"typescript": "^5.9.2"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
|
import * as glob from '@actions/glob'
|
||||||
import * as crypto from 'crypto'
|
import * as crypto from 'crypto'
|
||||||
import * as fs from 'fs'
|
import * as fs from 'fs'
|
||||||
import * as glob from '@actions/glob'
|
|
||||||
import * as path from 'path'
|
|
||||||
import * as stream from 'stream'
|
import * as stream from 'stream'
|
||||||
import * as util from 'util'
|
import * as util from 'util'
|
||||||
|
import * as path from 'path'
|
||||||
|
|
||||||
async function run(): Promise<void> {
|
async function run(): Promise<void> {
|
||||||
// arg0 -> node
|
// arg0 -> node
|
||||||
@@ -45,20 +45,11 @@ async function run(): Promise<void> {
|
|||||||
result.end()
|
result.end()
|
||||||
|
|
||||||
if (hasMatch) {
|
if (hasMatch) {
|
||||||
console.log(`Found ${count} files to hash.`)
|
console.log(`Find ${count} files to hash.`)
|
||||||
console.error(`__OUTPUT__${result.digest('hex')}__OUTPUT__`)
|
console.error(`__OUTPUT__${result.digest('hex')}__OUTPUT__`)
|
||||||
} else {
|
} else {
|
||||||
console.error(`__OUTPUT____OUTPUT__`)
|
console.error(`__OUTPUT____OUTPUT__`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
;(async () => {
|
run()
|
||||||
try {
|
|
||||||
const out = await run()
|
|
||||||
console.log(out)
|
|
||||||
process.exit(0)
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err)
|
|
||||||
process.exit(1)
|
|
||||||
}
|
|
||||||
})()
|
|
||||||
|
|||||||
@@ -3,11 +3,7 @@ PACKAGERUNTIME=$1
|
|||||||
PRECACHE=$2
|
PRECACHE=$2
|
||||||
|
|
||||||
NODE_URL=https://nodejs.org/dist
|
NODE_URL=https://nodejs.org/dist
|
||||||
NODE_ALPINE_URL=https://github.com/actions/alpine_nodejs/releases/download
|
NODE12_VERSION="12.13.1"
|
||||||
# When you update Node versions you must also create a new release of alpine_nodejs at that updated version.
|
|
||||||
# Follow the instructions here: https://github.com/actions/alpine_nodejs?tab=readme-ov-file#getting-started
|
|
||||||
NODE20_VERSION="20.19.5"
|
|
||||||
NODE24_VERSION="24.11.1"
|
|
||||||
|
|
||||||
get_abs_path() {
|
get_abs_path() {
|
||||||
# exploits the fact that pwd will print abs path when no args
|
# exploits the fact that pwd will print abs path when no args
|
||||||
@@ -57,22 +53,12 @@ function acquireExternalTool() {
|
|||||||
# Download from source to the partial file.
|
# Download from source to the partial file.
|
||||||
echo "Downloading $download_source"
|
echo "Downloading $download_source"
|
||||||
mkdir -p "$(dirname "$download_target")" || checkRC 'mkdir'
|
mkdir -p "$(dirname "$download_target")" || checkRC 'mkdir'
|
||||||
|
|
||||||
CURL_VERSION=$(curl --version | awk 'NR==1{print $2}')
|
|
||||||
echo "Curl version: $CURL_VERSION"
|
|
||||||
|
|
||||||
# curl -f Fail silently (no output at all) on HTTP errors (H)
|
# curl -f Fail silently (no output at all) on HTTP errors (H)
|
||||||
|
# -k Allow connections to SSL sites without certs (H)
|
||||||
# -S Show error. With -s, make curl show errors when they occur
|
# -S Show error. With -s, make curl show errors when they occur
|
||||||
# -L Follow redirects (H)
|
# -L Follow redirects (H)
|
||||||
# -o FILE Write to FILE instead of stdout
|
# -o FILE Write to FILE instead of stdout
|
||||||
# --retry 3 Retries transient errors 3 times (timeouts, 5xx)
|
curl -fkSL -o "$partial_target" "$download_source" 2>"${download_target}_download.log" || checkRC 'curl'
|
||||||
if [[ "$(printf '%s\n' "7.71.0" "$CURL_VERSION" | sort -V | head -n1)" != "7.71.0" ]]; then
|
|
||||||
# Curl version is less than or equal to 7.71.0, skipping retry-all-errors flag
|
|
||||||
curl -fSL --retry 3 -o "$partial_target" "$download_source" 2>"${download_target}_download.log" || checkRC 'curl'
|
|
||||||
else
|
|
||||||
# Curl version is greater than 7.71.0, running curl with --retry-all-errors flag
|
|
||||||
curl -fSL --retry 3 --retry-all-errors -o "$partial_target" "$download_source" 2>"${download_target}_download.log" || checkRC 'curl'
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Move the partial file to the download target.
|
# Move the partial file to the download target.
|
||||||
mv "$partial_target" "$download_target" || checkRC 'mv'
|
mv "$partial_target" "$download_target" || checkRC 'mv'
|
||||||
@@ -138,22 +124,8 @@ function acquireExternalTool() {
|
|||||||
|
|
||||||
# Download the external tools only for Windows.
|
# Download the external tools only for Windows.
|
||||||
if [[ "$PACKAGERUNTIME" == "win-x64" || "$PACKAGERUNTIME" == "win-x86" ]]; then
|
if [[ "$PACKAGERUNTIME" == "win-x64" || "$PACKAGERUNTIME" == "win-x86" ]]; then
|
||||||
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/$PACKAGERUNTIME/node.exe" node20/bin
|
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/$PACKAGERUNTIME/node.exe" node12/bin
|
||||||
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/$PACKAGERUNTIME/node.lib" node20/bin
|
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/$PACKAGERUNTIME/node.lib" node12/bin
|
||||||
acquireExternalTool "$NODE_URL/v${NODE24_VERSION}/$PACKAGERUNTIME/node.exe" node24/bin
|
|
||||||
acquireExternalTool "$NODE_URL/v${NODE24_VERSION}/$PACKAGERUNTIME/node.lib" node24/bin
|
|
||||||
if [[ "$PRECACHE" != "" ]]; then
|
|
||||||
acquireExternalTool "https://github.com/microsoft/vswhere/releases/download/2.6.7/vswhere.exe" vswhere
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Download the external tools only for Windows.
|
|
||||||
if [[ "$PACKAGERUNTIME" == "win-arm64" ]]; then
|
|
||||||
# todo: replace these with official release when available
|
|
||||||
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/$PACKAGERUNTIME/node.exe" node20/bin
|
|
||||||
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/$PACKAGERUNTIME/node.lib" node20/bin
|
|
||||||
acquireExternalTool "$NODE_URL/v${NODE24_VERSION}/$PACKAGERUNTIME/node.exe" node24/bin
|
|
||||||
acquireExternalTool "$NODE_URL/v${NODE24_VERSION}/$PACKAGERUNTIME/node.lib" node24/bin
|
|
||||||
if [[ "$PRECACHE" != "" ]]; then
|
if [[ "$PRECACHE" != "" ]]; then
|
||||||
acquireExternalTool "https://github.com/microsoft/vswhere/releases/download/2.6.7/vswhere.exe" vswhere
|
acquireExternalTool "https://github.com/microsoft/vswhere/releases/download/2.6.7/vswhere.exe" vswhere
|
||||||
fi
|
fi
|
||||||
@@ -161,29 +133,19 @@ fi
|
|||||||
|
|
||||||
# Download the external tools only for OSX.
|
# Download the external tools only for OSX.
|
||||||
if [[ "$PACKAGERUNTIME" == "osx-x64" ]]; then
|
if [[ "$PACKAGERUNTIME" == "osx-x64" ]]; then
|
||||||
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/node-v${NODE20_VERSION}-darwin-x64.tar.gz" node20 fix_nested_dir
|
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-darwin-x64.tar.gz" node12 fix_nested_dir
|
||||||
acquireExternalTool "$NODE_URL/v${NODE24_VERSION}/node-v${NODE24_VERSION}-darwin-x64.tar.gz" node24 fix_nested_dir
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$PACKAGERUNTIME" == "osx-arm64" ]]; then
|
|
||||||
# node.js v12 doesn't support macOS on arm64.
|
|
||||||
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/node-v${NODE20_VERSION}-darwin-arm64.tar.gz" node20 fix_nested_dir
|
|
||||||
acquireExternalTool "$NODE_URL/v${NODE24_VERSION}/node-v${NODE24_VERSION}-darwin-arm64.tar.gz" node24 fix_nested_dir
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Download the external tools for Linux PACKAGERUNTIMEs.
|
# Download the external tools for Linux PACKAGERUNTIMEs.
|
||||||
if [[ "$PACKAGERUNTIME" == "linux-x64" ]]; then
|
if [[ "$PACKAGERUNTIME" == "linux-x64" ]]; then
|
||||||
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/node-v${NODE20_VERSION}-linux-x64.tar.gz" node20 fix_nested_dir
|
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-linux-x64.tar.gz" node12 fix_nested_dir
|
||||||
acquireExternalTool "$NODE_ALPINE_URL/v${NODE20_VERSION}/node-v${NODE20_VERSION}-alpine-x64.tar.gz" node20_alpine
|
acquireExternalTool "https://vstsagenttools.blob.core.windows.net/tools/nodejs/${NODE12_VERSION}/alpine/x64/node-${NODE12_VERSION}-alpine-x64.tar.gz" node12_alpine
|
||||||
acquireExternalTool "$NODE_URL/v${NODE24_VERSION}/node-v${NODE24_VERSION}-linux-x64.tar.gz" node24 fix_nested_dir
|
|
||||||
acquireExternalTool "$NODE_ALPINE_URL/v${NODE24_VERSION}/node-v${NODE24_VERSION}-alpine-x64.tar.gz" node24_alpine
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$PACKAGERUNTIME" == "linux-arm64" ]]; then
|
if [[ "$PACKAGERUNTIME" == "linux-arm64" ]]; then
|
||||||
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/node-v${NODE20_VERSION}-linux-arm64.tar.gz" node20 fix_nested_dir
|
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-linux-arm64.tar.gz" node12 fix_nested_dir
|
||||||
acquireExternalTool "$NODE_URL/v${NODE24_VERSION}/node-v${NODE24_VERSION}-linux-arm64.tar.gz" node24 fix_nested_dir
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$PACKAGERUNTIME" == "linux-arm" ]]; then
|
if [[ "$PACKAGERUNTIME" == "linux-arm" ]]; then
|
||||||
acquireExternalTool "$NODE_URL/v${NODE20_VERSION}/node-v${NODE20_VERSION}-linux-armv7l.tar.gz" node20 fix_nested_dir
|
acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-linux-armv7l.tar.gz" node12 fix_nested_dir
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -3,156 +3,89 @@
|
|||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
|
||||||
var childProcess = require("child_process");
|
var childProcess = require("child_process");
|
||||||
var path = require("path");
|
var path = require("path")
|
||||||
|
|
||||||
var supported = ["linux", "darwin"];
|
var supported = ['linux', 'darwin']
|
||||||
|
|
||||||
if (supported.indexOf(process.platform) == -1) {
|
if (supported.indexOf(process.platform) == -1) {
|
||||||
console.log("Unsupported platform: " + process.platform);
|
console.log('Unsupported platform: ' + process.platform);
|
||||||
console.log("Supported platforms are: " + supported.toString());
|
console.log('Supported platforms are: ' + supported.toString());
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
var stopping = false;
|
var stopping = false;
|
||||||
var listener = null;
|
var listener = null;
|
||||||
|
|
||||||
var exitServiceAfterNFailures = Number(
|
var runService = function() {
|
||||||
process.env.GITHUB_ACTIONS_SERVICE_EXIT_AFTER_N_FAILURES
|
var listenerExePath = path.join(__dirname, '../bin/Runner.Listener');
|
||||||
);
|
var interactive = process.argv[2] === "interactive";
|
||||||
|
|
||||||
if (exitServiceAfterNFailures <= 0) {
|
if(!stopping) {
|
||||||
exitServiceAfterNFailures = NaN;
|
try {
|
||||||
|
if (interactive) {
|
||||||
|
console.log('Starting Runner listener interactively');
|
||||||
|
listener = childProcess.spawn(listenerExePath, ['run'], { env: process.env });
|
||||||
|
} else {
|
||||||
|
console.log('Starting Runner listener with startup type: service');
|
||||||
|
listener = childProcess.spawn(listenerExePath, ['run', '--startuptype', 'service'], { env: process.env });
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Started listener process');
|
||||||
|
|
||||||
|
listener.stdout.on('data', (data) => {
|
||||||
|
process.stdout.write(data.toString('utf8'));
|
||||||
|
});
|
||||||
|
|
||||||
|
listener.stderr.on('data', (data) => {
|
||||||
|
process.stdout.write(data.toString('utf8'));
|
||||||
|
});
|
||||||
|
|
||||||
|
listener.on('close', (code) => {
|
||||||
|
console.log(`Runner listener exited with error code ${code}`);
|
||||||
|
|
||||||
|
if (code === 0) {
|
||||||
|
console.log('Runner listener exit with 0 return code, stop the service, no retry needed.');
|
||||||
|
stopping = true;
|
||||||
|
} else if (code === 1) {
|
||||||
|
console.log('Runner listener exit with terminated error, stop the service, no retry needed.');
|
||||||
|
stopping = true;
|
||||||
|
} else if (code === 2) {
|
||||||
|
console.log('Runner listener exit with retryable error, re-launch runner in 5 seconds.');
|
||||||
|
} else if (code === 3) {
|
||||||
|
console.log('Runner listener exit because of updating, re-launch runner in 5 seconds.');
|
||||||
|
} else {
|
||||||
|
console.log('Runner listener exit with undefined return code, re-launch runner in 5 seconds.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!stopping) {
|
||||||
|
setTimeout(runService, 5000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch(ex) {
|
||||||
|
console.log(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var unknownFailureRetryCount = 0;
|
|
||||||
var retriableFailureRetryCount = 0;
|
|
||||||
|
|
||||||
var gracefulShutdown = function () {
|
|
||||||
console.log("Shutting down runner listener");
|
|
||||||
stopping = true;
|
|
||||||
if (listener) {
|
|
||||||
console.log("Sending SIGINT to runner listener to stop");
|
|
||||||
listener.kill("SIGINT");
|
|
||||||
|
|
||||||
console.log("Sending SIGKILL to runner listener");
|
|
||||||
setTimeout(() => listener.kill("SIGKILL"), 30000).unref();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var runService = function () {
|
|
||||||
var listenerExePath = path.join(__dirname, "../bin/Runner.Listener");
|
|
||||||
var interactive = process.argv[2] === "interactive";
|
|
||||||
|
|
||||||
if (!stopping) {
|
|
||||||
try {
|
|
||||||
if (interactive) {
|
|
||||||
console.log("Starting Runner listener interactively");
|
|
||||||
listener = childProcess.spawn(listenerExePath, ["run"], {
|
|
||||||
env: process.env,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.log("Starting Runner listener with startup type: service");
|
|
||||||
listener = childProcess.spawn(
|
|
||||||
listenerExePath,
|
|
||||||
["run", "--startuptype", "service"],
|
|
||||||
{ env: process.env }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Started listener process, pid: ${listener.pid}`);
|
|
||||||
|
|
||||||
listener.stdout.on("data", (data) => {
|
|
||||||
if (data.toString("utf8").includes("Listening for Jobs")) {
|
|
||||||
unknownFailureRetryCount = 0;
|
|
||||||
retriableFailureRetryCount = 0;
|
|
||||||
}
|
|
||||||
process.stdout.write(data.toString("utf8"));
|
|
||||||
});
|
|
||||||
|
|
||||||
listener.stderr.on("data", (data) => {
|
|
||||||
process.stdout.write(data.toString("utf8"));
|
|
||||||
});
|
|
||||||
|
|
||||||
listener.on("error", (err) => {
|
|
||||||
console.log(`Runner listener fail to start with error ${err.message}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
listener.on("close", (code) => {
|
|
||||||
console.log(`Runner listener exited with error code ${code}`);
|
|
||||||
|
|
||||||
if (code === 0) {
|
|
||||||
console.log(
|
|
||||||
"Runner listener exit with 0 return code, stop the service, no retry needed."
|
|
||||||
);
|
|
||||||
stopping = true;
|
|
||||||
} else if (code === 1) {
|
|
||||||
console.log(
|
|
||||||
"Runner listener exit with terminated error, stop the service, no retry needed."
|
|
||||||
);
|
|
||||||
stopping = true;
|
|
||||||
} else if (code === 2) {
|
|
||||||
console.log(
|
|
||||||
"Runner listener exit with retryable error, re-launch runner in 5 seconds."
|
|
||||||
);
|
|
||||||
unknownFailureRetryCount = 0;
|
|
||||||
retriableFailureRetryCount++;
|
|
||||||
if (retriableFailureRetryCount >= 10) {
|
|
||||||
console.error(
|
|
||||||
"Stopping the runner after 10 consecutive re-tryable failures"
|
|
||||||
);
|
|
||||||
stopping = true;
|
|
||||||
}
|
|
||||||
} else if (code === 3 || code === 4) {
|
|
||||||
console.log(
|
|
||||||
"Runner listener exit because of updating, re-launch runner in 5 seconds."
|
|
||||||
);
|
|
||||||
unknownFailureRetryCount = 0;
|
|
||||||
retriableFailureRetryCount++;
|
|
||||||
if (retriableFailureRetryCount >= 10) {
|
|
||||||
console.error(
|
|
||||||
"Stopping the runner after 10 consecutive re-tryable failures"
|
|
||||||
);
|
|
||||||
stopping = true;
|
|
||||||
}
|
|
||||||
} else if (code === 5) {
|
|
||||||
console.log(
|
|
||||||
"Runner listener exit with Session Conflict error, stop the service, no retry needed."
|
|
||||||
);
|
|
||||||
stopping = true;
|
|
||||||
} else {
|
|
||||||
var messagePrefix = "Runner listener exit with undefined return code";
|
|
||||||
unknownFailureRetryCount++;
|
|
||||||
retriableFailureRetryCount = 0;
|
|
||||||
if (
|
|
||||||
!isNaN(exitServiceAfterNFailures) &&
|
|
||||||
unknownFailureRetryCount >= exitServiceAfterNFailures
|
|
||||||
) {
|
|
||||||
console.error(
|
|
||||||
`${messagePrefix}, exiting service after ${unknownFailureRetryCount} consecutive failures`
|
|
||||||
);
|
|
||||||
stopping = true
|
|
||||||
} else {
|
|
||||||
console.log(`${messagePrefix}, re-launch runner in 5 seconds.`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!stopping) {
|
|
||||||
setTimeout(runService, 5000);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (ex) {
|
|
||||||
console.log(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
runService();
|
runService();
|
||||||
console.log("Started running service");
|
console.log('Started running service');
|
||||||
|
|
||||||
process.on("SIGINT", () => {
|
var gracefulShutdown = function(code) {
|
||||||
gracefulShutdown();
|
console.log('Shutting down runner listener');
|
||||||
|
stopping = true;
|
||||||
|
if (listener) {
|
||||||
|
console.log('Sending SIGINT to runner listener to stop');
|
||||||
|
listener.kill('SIGINT');
|
||||||
|
|
||||||
|
// TODO wait for 30 seconds and send a SIGKILL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
process.on('SIGINT', () => {
|
||||||
|
gracefulShutdown(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
process.on("SIGTERM", () => {
|
process.on('SIGTERM', () => {
|
||||||
gracefulShutdown();
|
gracefulShutdown(0);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -25,7 +25,5 @@
|
|||||||
</dict>
|
</dict>
|
||||||
<key>ProcessType</key>
|
<key>ProcessType</key>
|
||||||
<string>Interactive</string>
|
<string>Interactive</string>
|
||||||
<key>SessionCreate</key>
|
|
||||||
<true/>
|
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description={{Description}}
|
Description={{Description}}
|
||||||
After=network-online.target
|
After=network.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
ExecStart={{RunnerRoot}}/runsvc.sh
|
ExecStart={{RunnerRoot}}/runsvc.sh
|
||||||
|
|||||||
@@ -1,115 +0,0 @@
|
|||||||
const https = require('https')
|
|
||||||
const fs = require('fs')
|
|
||||||
const http = require('http')
|
|
||||||
const hostname = process.env['HOSTNAME'] || ''
|
|
||||||
const port = process.env['PORT'] || ''
|
|
||||||
const path = process.env['PATH'] || ''
|
|
||||||
const pat = process.env['PAT'] || ''
|
|
||||||
const proxyHost = process.env['PROXYHOST'] || ''
|
|
||||||
const proxyPort = process.env['PROXYPORT'] || ''
|
|
||||||
const proxyUsername = process.env['PROXYUSERNAME'] || ''
|
|
||||||
const proxyPassword = process.env['PROXYPASSWORD'] || ''
|
|
||||||
|
|
||||||
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0'
|
|
||||||
|
|
||||||
if (proxyHost === '') {
|
|
||||||
const options = {
|
|
||||||
hostname: hostname,
|
|
||||||
port: port,
|
|
||||||
path: path,
|
|
||||||
method: 'GET',
|
|
||||||
headers: {
|
|
||||||
'User-Agent': 'GitHubActionsRunnerCheck/1.0',
|
|
||||||
'Authorization': `token ${pat}`
|
|
||||||
},
|
|
||||||
}
|
|
||||||
const req = https.request(options, res => {
|
|
||||||
console.log(`statusCode: ${res.statusCode}`)
|
|
||||||
console.log(`headers: ${JSON.stringify(res.headers)}`)
|
|
||||||
let cert = socket.getPeerCertificate(true)
|
|
||||||
let certPEM = ''
|
|
||||||
let fingerprints = {}
|
|
||||||
while (cert != null && fingerprints[cert.fingerprint] != '1') {
|
|
||||||
fingerprints[cert.fingerprint] = '1'
|
|
||||||
certPEM = certPEM + '-----BEGIN CERTIFICATE-----\n'
|
|
||||||
let certEncoded = cert.raw.toString('base64')
|
|
||||||
for (let i = 0; i < certEncoded.length; i++) {
|
|
||||||
certPEM = certPEM + certEncoded[i]
|
|
||||||
if (i != certEncoded.length - 1 && (i + 1) % 64 == 0) {
|
|
||||||
certPEM = certPEM + '\n'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
certPEM = certPEM + '\n-----END CERTIFICATE-----\n'
|
|
||||||
cert = cert.issuerCertificate
|
|
||||||
}
|
|
||||||
console.log(certPEM)
|
|
||||||
fs.writeFileSync('./download_ca_cert.pem', certPEM)
|
|
||||||
res.on('data', d => {
|
|
||||||
process.stdout.write(d)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
req.on('error', error => {
|
|
||||||
console.error(error)
|
|
||||||
})
|
|
||||||
req.end()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const auth = 'Basic ' + Buffer.from(proxyUsername + ':' + proxyPassword).toString('base64')
|
|
||||||
|
|
||||||
const options = {
|
|
||||||
host: proxyHost,
|
|
||||||
port: proxyPort,
|
|
||||||
method: 'CONNECT',
|
|
||||||
path: `${hostname}:${port}`,
|
|
||||||
}
|
|
||||||
|
|
||||||
if (proxyUsername != '' || proxyPassword != '') {
|
|
||||||
options.headers = {
|
|
||||||
'Proxy-Authorization': auth,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
http.request(options).on('connect', (res, socket) => {
|
|
||||||
if (res.statusCode != 200) {
|
|
||||||
throw new Error(`Proxy returns code: ${res.statusCode}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
https.get({
|
|
||||||
host: hostname,
|
|
||||||
port: port,
|
|
||||||
socket: socket,
|
|
||||||
agent: false,
|
|
||||||
path: '/',
|
|
||||||
headers: {
|
|
||||||
'User-Agent': 'GitHubActionsRunnerCheck/1.0',
|
|
||||||
'Authorization': `token ${pat}`
|
|
||||||
}
|
|
||||||
}, (res) => {
|
|
||||||
let cert = res.socket.getPeerCertificate(true)
|
|
||||||
let certPEM = ''
|
|
||||||
let fingerprints = {}
|
|
||||||
while (cert != null && fingerprints[cert.fingerprint] != '1') {
|
|
||||||
fingerprints[cert.fingerprint] = '1'
|
|
||||||
certPEM = certPEM + '-----BEGIN CERTIFICATE-----\n'
|
|
||||||
let certEncoded = cert.raw.toString('base64')
|
|
||||||
for (let i = 0; i < certEncoded.length; i++) {
|
|
||||||
certPEM = certPEM + certEncoded[i]
|
|
||||||
if (i != certEncoded.length - 1 && (i + 1) % 64 == 0) {
|
|
||||||
certPEM = certPEM + '\n'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
certPEM = certPEM + '\n-----END CERTIFICATE-----\n'
|
|
||||||
cert = cert.issuerCertificate
|
|
||||||
}
|
|
||||||
console.log(certPEM)
|
|
||||||
fs.writeFileSync('./download_ca_cert.pem', certPEM)
|
|
||||||
console.log(`statusCode: ${res.statusCode}`)
|
|
||||||
console.log(`headers: ${JSON.stringify(res.headers)}`)
|
|
||||||
res.on('data', d => {
|
|
||||||
process.stdout.write(d)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}).on('error', (err) => {
|
|
||||||
console.error('error', err)
|
|
||||||
}).end()
|
|
||||||
}
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
const https = require('https')
|
|
||||||
const http = require('http')
|
|
||||||
const hostname = process.env['HOSTNAME'] || ''
|
|
||||||
const port = process.env['PORT'] || ''
|
|
||||||
const path = process.env['PATH'] || ''
|
|
||||||
const pat = process.env['PAT'] || ''
|
|
||||||
const proxyHost = process.env['PROXYHOST'] || ''
|
|
||||||
const proxyPort = process.env['PROXYPORT'] || ''
|
|
||||||
const proxyUsername = process.env['PROXYUSERNAME'] || ''
|
|
||||||
const proxyPassword = process.env['PROXYPASSWORD'] || ''
|
|
||||||
|
|
||||||
if (proxyHost === '') {
|
|
||||||
const options = {
|
|
||||||
hostname: hostname,
|
|
||||||
port: port,
|
|
||||||
path: path,
|
|
||||||
method: 'GET',
|
|
||||||
headers: {
|
|
||||||
'User-Agent': 'GitHubActionsRunnerCheck/1.0',
|
|
||||||
'Authorization': `token ${pat}`,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const req = https.request(options, res => {
|
|
||||||
console.log(`statusCode: ${res.statusCode}`)
|
|
||||||
console.log(`headers: ${JSON.stringify(res.headers)}`)
|
|
||||||
|
|
||||||
res.on('data', d => {
|
|
||||||
process.stdout.write(d)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
req.on('error', error => {
|
|
||||||
console.error(error)
|
|
||||||
})
|
|
||||||
req.end()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const proxyAuth = 'Basic ' + Buffer.from(proxyUsername + ':' + proxyPassword).toString('base64')
|
|
||||||
const options = {
|
|
||||||
hostname: proxyHost,
|
|
||||||
port: proxyPort,
|
|
||||||
method: 'CONNECT',
|
|
||||||
path: `${hostname}:${port}`
|
|
||||||
}
|
|
||||||
|
|
||||||
if (proxyUsername != '' || proxyPassword != '') {
|
|
||||||
options.headers = {
|
|
||||||
'Proxy-Authorization': proxyAuth,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
http.request(options).on('connect', (res, socket) => {
|
|
||||||
if (res.statusCode != 200) {
|
|
||||||
throw new Error(`Proxy returns code: ${res.statusCode}`)
|
|
||||||
}
|
|
||||||
https.get({
|
|
||||||
host: hostname,
|
|
||||||
port: port,
|
|
||||||
socket: socket,
|
|
||||||
agent: false,
|
|
||||||
path: path,
|
|
||||||
headers: {
|
|
||||||
'User-Agent': 'GitHubActionsRunnerCheck/1.0',
|
|
||||||
'Authorization': `token ${pat}`,
|
|
||||||
}
|
|
||||||
}, (res) => {
|
|
||||||
console.log(`statusCode: ${res.statusCode}`)
|
|
||||||
console.log(`headers: ${JSON.stringify(res.headers)}`)
|
|
||||||
|
|
||||||
res.on('data', d => {
|
|
||||||
process.stdout.write(d)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}).on('error', (err) => {
|
|
||||||
console.error('error', err)
|
|
||||||
}).end()
|
|
||||||
}
|
|
||||||
@@ -17,13 +17,7 @@ RUNNER_ROOT=`pwd`
|
|||||||
|
|
||||||
LAUNCH_PATH="${HOME}/Library/LaunchAgents"
|
LAUNCH_PATH="${HOME}/Library/LaunchAgents"
|
||||||
PLIST_PATH="${LAUNCH_PATH}/${SVC_NAME}.plist"
|
PLIST_PATH="${LAUNCH_PATH}/${SVC_NAME}.plist"
|
||||||
TEMPLATE_PATH=$GITHUB_ACTIONS_RUNNER_SERVICE_TEMPLATE
|
TEMPLATE_PATH=./bin/actions.runner.plist.template
|
||||||
IS_CUSTOM_TEMPLATE=0
|
|
||||||
if [[ -z $TEMPLATE_PATH ]]; then
|
|
||||||
TEMPLATE_PATH=./bin/actions.runner.plist.template
|
|
||||||
else
|
|
||||||
IS_CUSTOM_TEMPLATE=1
|
|
||||||
fi
|
|
||||||
TEMP_PATH=./bin/actions.runner.plist.temp
|
TEMP_PATH=./bin/actions.runner.plist.temp
|
||||||
CONFIG_PATH=.service
|
CONFIG_PATH=.service
|
||||||
|
|
||||||
@@ -35,11 +29,7 @@ function failed()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if [ ! -f "${TEMPLATE_PATH}" ]; then
|
if [ ! -f "${TEMPLATE_PATH}" ]; then
|
||||||
if [[ $IS_CUSTOM_TEMPLATE = 0 ]]; then
|
failed "Must run from runner root or install is corrupt"
|
||||||
failed "Must run from runner root or install is corrupt"
|
|
||||||
else
|
|
||||||
failed "Service file at '$GITHUB_ACTIONS_RUNNER_SERVICE_TEMPLATE' using GITHUB_ACTIONS_RUNNER_SERVICE_TEMPLATE env variable is not found"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
function install()
|
function install()
|
||||||
@@ -63,7 +53,7 @@ function install()
|
|||||||
mkdir -p "${log_path}" || failed "failed to create ${log_path}"
|
mkdir -p "${log_path}" || failed "failed to create ${log_path}"
|
||||||
|
|
||||||
echo Creating ${PLIST_PATH}
|
echo Creating ${PLIST_PATH}
|
||||||
sed "s/{{User}}/${USER:-$SUDO_USER}/g; s/{{SvcName}}/$SVC_NAME/g; s@{{RunnerRoot}}@${RUNNER_ROOT}@g; s@{{UserHome}}@$HOME@g;" "${TEMPLATE_PATH}" > "${TEMP_PATH}" || failed "failed to create replacement temp file"
|
sed "s/{{User}}/${SUDO_USER:-$USER}/g; s/{{SvcName}}/$SVC_NAME/g; s@{{RunnerRoot}}@${RUNNER_ROOT}@g; s@{{UserHome}}@$HOME@g;" "${TEMPLATE_PATH}" > "${TEMP_PATH}" || failed "failed to create replacement temp file"
|
||||||
mv "${TEMP_PATH}" "${PLIST_PATH}" || failed "failed to copy plist"
|
mv "${TEMP_PATH}" "${PLIST_PATH}" || failed "failed to copy plist"
|
||||||
|
|
||||||
# Since we started with sudo, runsvc.sh will be owned by root. Change this to current login user.
|
# Since we started with sudo, runsvc.sh will be owned by root. Change this to current login user.
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -49,73 +49,69 @@ then
|
|||||||
cat /etc/debian_version
|
cat /etc/debian_version
|
||||||
echo "------------------------------"
|
echo "------------------------------"
|
||||||
|
|
||||||
# prefer apt-get over apt
|
# prefer apt over apt-get
|
||||||
command -v apt-get
|
command -v apt
|
||||||
if [ $? -eq 0 ]
|
if [ $? -eq 0 ]
|
||||||
then
|
then
|
||||||
apt_get=apt-get
|
apt update && apt install -y liblttng-ust0 libkrb5-3 zlib1g
|
||||||
else
|
if [ $? -ne 0 ]
|
||||||
command -v apt
|
|
||||||
if [ $? -eq 0 ]
|
|
||||||
then
|
then
|
||||||
apt_get=apt
|
echo "'apt' failed with exit code '$?'"
|
||||||
else
|
|
||||||
echo "Found neither 'apt-get' nor 'apt'"
|
|
||||||
print_errormessage
|
print_errormessage
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
|
|
||||||
$apt_get update && $apt_get install -y libkrb5-3 zlib1g
|
# libissl version prefer: libssl1.1 -> libssl1.0.2 -> libssl1.0.0
|
||||||
if [ $? -ne 0 ]
|
apt install -y libssl1.1$ || apt install -y libssl1.0.2$ || apt install -y libssl1.0.0$
|
||||||
then
|
if [ $? -ne 0 ]
|
||||||
echo "'$apt_get' failed with exit code '$?'"
|
|
||||||
print_errormessage
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
apt_get_with_fallbacks() {
|
|
||||||
$apt_get install -y $1
|
|
||||||
fail=$?
|
|
||||||
if [ $fail -eq 0 ]
|
|
||||||
then
|
then
|
||||||
if [ "${1#"${1%?}"}" = '$' ]; then
|
echo "'apt' failed with exit code '$?'"
|
||||||
dpkg -l "${1%?}" > /dev/null 2> /dev/null
|
print_errormessage
|
||||||
fail=$?
|
exit 1
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
if [ $fail -ne 0 ]
|
|
||||||
|
# libicu version prefer: libicu66 -> libicu63 -> libicu60 -> libicu57 -> libicu55 -> libicu52
|
||||||
|
apt install -y libicu66 || apt install -y libicu63 || apt install -y libicu60 || apt install -y libicu57 || apt install -y libicu55 || apt install -y libicu52
|
||||||
|
if [ $? -ne 0 ]
|
||||||
then
|
then
|
||||||
shift
|
echo "'apt' failed with exit code '$?'"
|
||||||
if [ -n "$1" ]
|
print_errormessage
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
command -v apt-get
|
||||||
|
if [ $? -eq 0 ]
|
||||||
|
then
|
||||||
|
apt-get update && apt-get install -y liblttng-ust0 libkrb5-3 zlib1g
|
||||||
|
if [ $? -ne 0 ]
|
||||||
then
|
then
|
||||||
apt_get_with_fallbacks "$@"
|
echo "'apt-get' failed with exit code '$?'"
|
||||||
|
print_errormessage
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# libissl version prefer: libssl1.1 -> libssl1.0.2 -> libssl1.0.0
|
||||||
|
apt-get install -y libssl1.1$ || apt-get install -y libssl1.0.2$ || apt install -y libssl1.0.0$
|
||||||
|
if [ $? -ne 0 ]
|
||||||
|
then
|
||||||
|
echo "'apt-get' failed with exit code '$?'"
|
||||||
|
print_errormessage
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# libicu version prefer: libicu66 -> libicu63 -> libicu60 -> libicu57 -> libicu55 -> libicu52
|
||||||
|
apt-get install -y libicu66 || apt-get install -y libicu63 || apt-get install -y libicu60 || apt install -y libicu57 || apt install -y libicu55 || apt install -y libicu52
|
||||||
|
if [ $? -ne 0 ]
|
||||||
|
then
|
||||||
|
echo "'apt-get' failed with exit code '$?'"
|
||||||
|
print_errormessage
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Can not find 'apt' or 'apt-get'"
|
||||||
|
print_errormessage
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
}
|
|
||||||
|
|
||||||
apt_get_with_fallbacks liblttng-ust1 liblttng-ust0
|
|
||||||
if [ $? -ne 0 ]
|
|
||||||
then
|
|
||||||
echo "'$apt_get' failed with exit code '$?'"
|
|
||||||
print_errormessage
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
apt_get_with_fallbacks libssl1.1$ libssl1.0.2$ libssl1.0.0$
|
|
||||||
if [ $? -ne 0 ]
|
|
||||||
then
|
|
||||||
echo "'$apt_get' failed with exit code '$?'"
|
|
||||||
print_errormessage
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
apt_get_with_fallbacks libicu76 libicu75 libicu74 libicu73 libicu72 libicu71 libicu70 libicu69 libicu68 libicu67 libicu66 libicu65 libicu63 libicu60 libicu57 libicu55 libicu52
|
|
||||||
if [ $? -ne 0 ]
|
|
||||||
then
|
|
||||||
echo "'$apt_get' failed with exit code '$?'"
|
|
||||||
print_errormessage
|
|
||||||
exit 1
|
|
||||||
fi
|
fi
|
||||||
elif [ -e /etc/redhat-release ]
|
elif [ -e /etc/redhat-release ]
|
||||||
then
|
then
|
||||||
|
|||||||
@@ -10,11 +10,10 @@ if [ -f ".path" ]; then
|
|||||||
echo ".path=${PATH}"
|
echo ".path=${PATH}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
nodever="node20"
|
|
||||||
|
|
||||||
# insert anything to setup env when running as a service
|
# insert anything to setup env when running as a service
|
||||||
|
|
||||||
# run the host process which keep the listener alive
|
# run the host process which keep the listener alive
|
||||||
./externals/$nodever/bin/node ./bin/RunnerService.js &
|
./externals/node12/bin/node ./bin/RunnerService.js &
|
||||||
PID=$!
|
PID=$!
|
||||||
wait $PID
|
wait $PID
|
||||||
trap - TERM INT
|
trap - TERM INT
|
||||||
|
|||||||
@@ -10,13 +10,7 @@ arg_2=${2}
|
|||||||
RUNNER_ROOT=`pwd`
|
RUNNER_ROOT=`pwd`
|
||||||
|
|
||||||
UNIT_PATH=/etc/systemd/system/${SVC_NAME}
|
UNIT_PATH=/etc/systemd/system/${SVC_NAME}
|
||||||
TEMPLATE_PATH=$GITHUB_ACTIONS_RUNNER_SERVICE_TEMPLATE
|
TEMPLATE_PATH=./bin/actions.runner.service.template
|
||||||
IS_CUSTOM_TEMPLATE=0
|
|
||||||
if [[ -z $TEMPLATE_PATH ]]; then
|
|
||||||
TEMPLATE_PATH=./bin/actions.runner.service.template
|
|
||||||
else
|
|
||||||
IS_CUSTOM_TEMPLATE=1
|
|
||||||
fi
|
|
||||||
TEMP_PATH=./bin/actions.runner.service.temp
|
TEMP_PATH=./bin/actions.runner.service.temp
|
||||||
CONFIG_PATH=.service
|
CONFIG_PATH=.service
|
||||||
|
|
||||||
@@ -37,11 +31,7 @@ function failed()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if [ ! -f "${TEMPLATE_PATH}" ]; then
|
if [ ! -f "${TEMPLATE_PATH}" ]; then
|
||||||
if [[ $IS_CUSTOM_TEMPLATE = 0 ]]; then
|
failed "Must run from runner root or install is corrupt"
|
||||||
failed "Must run from runner root or install is corrupt"
|
|
||||||
else
|
|
||||||
failed "Service file at '$GITHUB_ACTIONS_RUNNER_SERVICE_TEMPLATE' using GITHUB_ACTIONS_RUNNER_SERVICE_TEMPLATE env variable is not found"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#check if we run as root
|
#check if we run as root
|
||||||
@@ -116,37 +106,25 @@ function stop()
|
|||||||
|
|
||||||
function uninstall()
|
function uninstall()
|
||||||
{
|
{
|
||||||
if service_exists; then
|
stop
|
||||||
stop
|
systemctl disable ${SVC_NAME} || failed "failed to disable ${SVC_NAME}"
|
||||||
systemctl disable ${SVC_NAME} || failed "failed to disable ${SVC_NAME}"
|
rm "${UNIT_PATH}" || failed "failed to delete ${UNIT_PATH}"
|
||||||
rm "${UNIT_PATH}" || failed "failed to delete ${UNIT_PATH}"
|
|
||||||
else
|
|
||||||
echo "Service ${SVC_NAME} is not installed"
|
|
||||||
fi
|
|
||||||
if [ -f "${CONFIG_PATH}" ]; then
|
if [ -f "${CONFIG_PATH}" ]; then
|
||||||
rm "${CONFIG_PATH}" || failed "failed to delete ${CONFIG_PATH}"
|
rm "${CONFIG_PATH}" || failed "failed to delete ${CONFIG_PATH}"
|
||||||
fi
|
fi
|
||||||
systemctl daemon-reload || failed "failed to reload daemons"
|
systemctl daemon-reload || failed "failed to reload daemons"
|
||||||
}
|
}
|
||||||
|
|
||||||
function service_exists() {
|
|
||||||
if [ -f "${UNIT_PATH}" ]; then
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function status()
|
function status()
|
||||||
{
|
{
|
||||||
if service_exists; then
|
if [ -f "${UNIT_PATH}" ]; then
|
||||||
echo
|
echo
|
||||||
echo "${UNIT_PATH}"
|
echo "${UNIT_PATH}"
|
||||||
else
|
else
|
||||||
echo
|
echo
|
||||||
echo "not installed"
|
echo "not installed"
|
||||||
echo
|
echo
|
||||||
exit 1
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
systemctl --no-pager status ${SVC_NAME}
|
systemctl --no-pager status ${SVC_NAME}
|
||||||
|
|||||||
@@ -120,9 +120,6 @@ if ERRORLEVEL 1 (
|
|||||||
|
|
||||||
echo [%date% %time%] Update succeed >> "%logfile%" 2>&1
|
echo [%date% %time%] Update succeed >> "%logfile%" 2>&1
|
||||||
|
|
||||||
type nul > update.finished
|
|
||||||
echo [%date% %time%] update.finished file creation succeed >> "%logfile%" 2>&1
|
|
||||||
|
|
||||||
rem rename the update log file with %logfile%.succeed/.failed/succeedneedrestart
|
rem rename the update log file with %logfile%.succeed/.failed/succeedneedrestart
|
||||||
rem runner service host can base on the log file name determin the result of the runner update
|
rem runner service host can base on the log file name determin the result of the runner update
|
||||||
echo [%date% %time%] Rename "%logfile%" to be "%logfile%.succeed" >> "%logfile%" 2>&1
|
echo [%date% %time%] Rename "%logfile%" to be "%logfile%.succeed" >> "%logfile%" 2>&1
|
||||||
|
|||||||
91
src/Misc/layoutbin/update.sh.template
Executable file → Normal file
91
src/Misc/layoutbin/update.sh.template
Executable file → Normal file
@@ -18,8 +18,6 @@ downloadrunnerversion=_DOWNLOAD_RUNNER_VERSION_
|
|||||||
logfile="_UPDATE_LOG_"
|
logfile="_UPDATE_LOG_"
|
||||||
restartinteractiverunner=_RESTART_INTERACTIVE_RUNNER_
|
restartinteractiverunner=_RESTART_INTERACTIVE_RUNNER_
|
||||||
|
|
||||||
telemetryfile="$rootfolder/_diag/.telemetry"
|
|
||||||
|
|
||||||
# log user who run the script
|
# log user who run the script
|
||||||
date "+[%F %T-%4N] --------whoami--------" >> "$logfile" 2>&1
|
date "+[%F %T-%4N] --------whoami--------" >> "$logfile" 2>&1
|
||||||
whoami >> "$logfile" 2>&1
|
whoami >> "$logfile" 2>&1
|
||||||
@@ -30,13 +28,13 @@ date "+[%F %T-%4N] Waiting for $runnerprocessname ($runnerpid) to complete" >> "
|
|||||||
while [ -e /proc/$runnerpid ]
|
while [ -e /proc/$runnerpid ]
|
||||||
do
|
do
|
||||||
date "+[%F %T-%4N] Process $runnerpid still running" >> "$logfile" 2>&1
|
date "+[%F %T-%4N] Process $runnerpid still running" >> "$logfile" 2>&1
|
||||||
"$rootfolder"/safe_sleep.sh 2
|
ping -c 2 127.0.0.1 >nul
|
||||||
done
|
done
|
||||||
date "+[%F %T-%4N] Process $runnerpid finished running" >> "$logfile" 2>&1
|
date "+[%F %T-%4N] Process $runnerpid finished running" >> "$logfile" 2>&1
|
||||||
|
|
||||||
# start re-organize folders
|
# start re-organize folders
|
||||||
date "+[%F %T-%4N] Sleep 1 more second to make sure process exited" >> "$logfile" 2>&1
|
date "+[%F %T-%4N] Sleep 1 more second to make sure process exited" >> "$logfile" 2>&1
|
||||||
"$rootfolder"/safe_sleep.sh 1
|
ping -c 2 127.0.0.1 >nul
|
||||||
|
|
||||||
# the folder structure under runner root will be
|
# the folder structure under runner root will be
|
||||||
# ./bin -> bin.2.100.0 (junction folder)
|
# ./bin -> bin.2.100.0 (junction folder)
|
||||||
@@ -120,93 +118,8 @@ then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# fix upgrade issue with macOS when running as a service
|
|
||||||
attemptedtargetedfix=0
|
|
||||||
currentplatform=$(uname | awk '{print tolower($0)}')
|
|
||||||
if [[ "$currentplatform" == 'darwin' && $restartinteractiverunner -eq 0 ]]; then
|
|
||||||
# We needed a fix for https://github.com/actions/runner/issues/743
|
|
||||||
# We will recreate the ./externals/nodeXY/bin/node of the past runner version that launched the runnerlistener service
|
|
||||||
# Otherwise mac gatekeeper kills the processes we spawn on creation as we are running a process with no backing file
|
|
||||||
|
|
||||||
# We need the pid for the nodejs loop, get that here, its the parent of the runner C# pid
|
|
||||||
# assumption here is only one process is invoking rootfolder/runsvc.sh
|
|
||||||
procgroup=$(ps x -o pgid,command | grep "$rootfolder/runsvc.sh" | grep -v grep | awk '{print $1}')
|
|
||||||
if [[ $? -eq 0 && -n "$procgroup" ]]
|
|
||||||
then
|
|
||||||
# inspect the open file handles to find the node process
|
|
||||||
# we can't actually inspect the process using ps because it uses relative paths and doesn't follow symlinks
|
|
||||||
# Try finding node24 first, then fallback to earlier versions if needed
|
|
||||||
nodever="node24"
|
|
||||||
path=$(lsof -a -g "$procgroup" -F n | grep $nodever/bin/node | grep externals | tail -1 | cut -c2-)
|
|
||||||
if [[ $? -ne 0 || -z "$path" ]] # Fallback if RunnerService.js was started with node20
|
|
||||||
then
|
|
||||||
nodever="node20"
|
|
||||||
path=$(lsof -a -g "$procgroup" -F n | grep $nodever/bin/node | grep externals | tail -1 | cut -c2-)
|
|
||||||
if [[ $? -ne 0 || -z "$path" ]] # Fallback if RunnerService.js was started with node16
|
|
||||||
then
|
|
||||||
nodever="node16"
|
|
||||||
path=$(lsof -a -g "$procgroup" -F n | grep $nodever/bin/node | grep externals | tail -1 | cut -c2-)
|
|
||||||
if [[ $? -ne 0 || -z "$path" ]] # Fallback if RunnerService.js was started with node12
|
|
||||||
then
|
|
||||||
nodever="node12"
|
|
||||||
path=$(lsof -a -g "$procgroup" -F n | grep $nodever/bin/node | grep externals | tail -1 | cut -c2-)
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
if [[ $? -eq 0 && -n "$path" ]]
|
|
||||||
then
|
|
||||||
# trim the last 5 characters of the path '/node'
|
|
||||||
trimmedpath=$(dirname "$path")
|
|
||||||
if [[ $? -eq 0 && -n "$trimmedpath" ]]
|
|
||||||
then
|
|
||||||
attemptedtargetedfix=1
|
|
||||||
# Create the path if it does not exist
|
|
||||||
if [[ ! -e "$path" ]]
|
|
||||||
then
|
|
||||||
date "+[%F %T-%4N] Creating fallback node at path $path" >> "$logfile" 2>&1
|
|
||||||
mkdir -p "$trimmedpath"
|
|
||||||
cp "$rootfolder/externals/$nodever/bin/node" "$path"
|
|
||||||
else
|
|
||||||
date "+[%F %T-%4N] Path for fallback node exists, skipping creating $path" >> "$logfile" 2>&1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
date "+[%F %T-%4N] DarwinRunnerUpgrade: Failed to trim runner path. TrimmedPath: $trimmedpath, path: $path, pgid: $procgroup, root: $rootfolder" >> "$logfile" 2>&1
|
|
||||||
date "+[%F %T-%4N] DarwinRunnerUpgrade: Failed to trim runner path. TrimmedPath: $trimmedpath, path: $path, pgid: $procgroup, root: $rootfolder" >> "$telemetryfile" 2>&1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
date "+[%F %T-%4N] DarwinRunnerUpgrade: Failed to find runner path. Path: $path, pgid: $procgroup, root: $rootfolder" >> "$logfile" 2>&1
|
|
||||||
date "+[%F %T-%4N] DarwinRunnerUpgrade: Failed to find runner path. Path: $path, pgid: $procgroup, root: $rootfolder" >> "$telemetryfile" 2>&1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
runproc=$(ps x -o pgid,command | grep "run.sh" | grep -v grep | awk '{print $1}')
|
|
||||||
if [[ $? -eq 0 && -n "$runproc" ]]
|
|
||||||
then
|
|
||||||
date "+[%F %T-%4N] Running as ephemeral using run.sh, no need to recreate node folder" >> "$logfile" 2>&1
|
|
||||||
else
|
|
||||||
date "+[%F %T-%4N] DarwinRunnerUpgrade: Failed to find runner pgid. pgid: $procgroup, root: $rootfolder" >> "$logfile" 2>&1
|
|
||||||
date "+[%F %T-%4N] DarwinRunnerUpgrade: Failed to find runner pgid. pgid: $procgroup, root: $rootfolder" >> "$telemetryfile" 2>&1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# update runsvc.sh
|
|
||||||
if [ -f "$rootfolder/runsvc.sh" ]
|
|
||||||
then
|
|
||||||
date "+[%F %T-%4N] Update runsvc.sh" >> "$logfile" 2>&1
|
|
||||||
cat "$rootfolder/bin/runsvc.sh" > "$rootfolder/runsvc.sh"
|
|
||||||
if [ $? -ne 0 ]
|
|
||||||
then
|
|
||||||
date "+[%F %T-%4N] Can't update $rootfolder/runsvc.sh using $rootfolder/bin/runsvc.sh" >> "$logfile" 2>&1
|
|
||||||
mv -fv "$logfile" "$logfile.failed"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
date "+[%F %T-%4N] Update succeed" >> "$logfile"
|
date "+[%F %T-%4N] Update succeed" >> "$logfile"
|
||||||
|
|
||||||
touch update.finished
|
|
||||||
date "+[%F %T-%4N] update.finished file creation succeed" >> "$logfile"
|
|
||||||
|
|
||||||
# rename the update log file with %logfile%.succeed/.failed/succeedneedrestart
|
# rename the update log file with %logfile%.succeed/.failed/succeedneedrestart
|
||||||
# runner service host can base on the log file name determin the result of the runner update
|
# runner service host can base on the log file name determin the result of the runner update
|
||||||
date "+[%F %T-%4N] Rename $logfile to be $logfile.succeed" >> "$logfile" 2>&1
|
date "+[%F %T-%4N] Rename $logfile to be $logfile.succeed" >> "$logfile" 2>&1
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ if [ $user_id -eq 0 -a -z "$RUNNER_ALLOW_RUNASROOT" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check dotnet Core 6.0 dependencies for Linux
|
# Check dotnet core 3.0 dependencies for Linux
|
||||||
if [[ (`uname` == "Linux") ]]
|
if [[ (`uname` == "Linux") ]]
|
||||||
then
|
then
|
||||||
command -v ldd > /dev/null
|
command -v ldd > /dev/null
|
||||||
@@ -18,26 +18,24 @@ then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
message="Execute sudo ./bin/installdependencies.sh to install any missing Dotnet Core 6.0 dependencies."
|
|
||||||
|
|
||||||
ldd ./bin/libcoreclr.so | grep 'not found'
|
ldd ./bin/libcoreclr.so | grep 'not found'
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
echo "Dependencies is missing for Dotnet Core 6.0"
|
echo "Dependencies is missing for Dotnet Core 3.0"
|
||||||
echo $message
|
echo "Execute ./bin/installdependencies.sh to install any missing Dotnet Core 3.0 dependencies."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ldd ./bin/libSystem.Security.Cryptography.Native.OpenSsl.so | grep 'not found'
|
ldd ./bin/System.Security.Cryptography.Native.OpenSsl.so | grep 'not found'
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
echo "Dependencies is missing for Dotnet Core 6.0"
|
echo "Dependencies is missing for Dotnet Core 3.0"
|
||||||
echo $message
|
echo "Execute ./bin/installdependencies.sh to install any missing Dotnet Core 3.0 dependencies."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ldd ./bin/libSystem.IO.Compression.Native.so | grep 'not found'
|
ldd ./bin/System.IO.Compression.Native.so | grep 'not found'
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
echo "Dependencies is missing for Dotnet Core 6.0"
|
echo "Dependencies is missing for Dotnet Core 3.0"
|
||||||
echo $message
|
echo "Execute ./bin/installdependencies.sh to install any missing Dotnet Core 3.0 dependencies."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -52,10 +50,10 @@ then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
libpath=${LD_LIBRARY_PATH:-}
|
libpath=${LD_LIBRARY_PATH:-}
|
||||||
$LDCONFIG_COMMAND -NXv ${libpath//:/ } 2>&1 | grep libicu >/dev/null 2>&1
|
$LDCONFIG_COMMAND -NXv ${libpath//:/} 2>&1 | grep libicu >/dev/null 2>&1
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
echo "Libicu's dependencies is missing for Dotnet Core 6.0"
|
echo "Libicu's dependencies is missing for Dotnet Core 3.0"
|
||||||
echo $message
|
echo "Execute ./bin/installdependencies.sh to install any missing Dotnet Core 3.0 dependencies."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ varCheckList=(
|
|||||||
'ANT_HOME'
|
'ANT_HOME'
|
||||||
'M2_HOME'
|
'M2_HOME'
|
||||||
'ANDROID_HOME'
|
'ANDROID_HOME'
|
||||||
'ANDROID_SDK_ROOT'
|
|
||||||
'GRADLE_HOME'
|
'GRADLE_HOME'
|
||||||
'NVM_BIN'
|
'NVM_BIN'
|
||||||
'NVM_PATH'
|
'NVM_PATH'
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
@echo off
|
|
||||||
SET UPDATEFILE=update.finished
|
|
||||||
"%~dp0\bin\Runner.Listener.exe" run %*
|
|
||||||
|
|
||||||
rem using `if %ERRORLEVEL% EQU N` instead of `if ERRORLEVEL N`
|
|
||||||
rem `if ERRORLEVEL N` means: error level is N or MORE
|
|
||||||
|
|
||||||
if %ERRORLEVEL% EQU 0 (
|
|
||||||
echo "Runner listener exit with 0 return code, stop the service, no retry needed."
|
|
||||||
exit /b 0
|
|
||||||
)
|
|
||||||
|
|
||||||
if %ERRORLEVEL% EQU 1 (
|
|
||||||
echo "Runner listener exit with terminated error, stop the service, no retry needed."
|
|
||||||
exit /b 0
|
|
||||||
)
|
|
||||||
|
|
||||||
if %ERRORLEVEL% EQU 2 (
|
|
||||||
echo "Runner listener exit with retryable error, re-launch runner in 5 seconds."
|
|
||||||
ping 127.0.0.1 -n 6 -w 1000 >NUL
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
if %ERRORLEVEL% EQU 3 (
|
|
||||||
rem Wait for 30 seconds or for flag file to exists for the ephemeral runner update process finish
|
|
||||||
echo "Runner listener exit because of updating, re-launch runner after successful update"
|
|
||||||
FOR /L %%G IN (1,1,30) DO (
|
|
||||||
IF EXIST %UPDATEFILE% (
|
|
||||||
echo "Update finished successfully."
|
|
||||||
del %FILE%
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
ping 127.0.0.1 -n 2 -w 1000 >NUL
|
|
||||||
)
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
if %ERRORLEVEL% EQU 4 (
|
|
||||||
rem Wait for 30 seconds or for flag file to exists for the runner update process finish
|
|
||||||
echo "Runner listener exit because of updating, re-launch runner after successful update"
|
|
||||||
FOR /L %%G IN (1,1,30) DO (
|
|
||||||
IF EXIST %UPDATEFILE% (
|
|
||||||
echo "Update finished successfully."
|
|
||||||
del %FILE%
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
ping 127.0.0.1 -n 2 -w 1000 >NUL
|
|
||||||
)
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
if %ERRORLEVEL% EQU 5 (
|
|
||||||
echo "Runner listener exit with Session Conflict error, stop the service, no retry needed."
|
|
||||||
exit /b 0
|
|
||||||
)
|
|
||||||
|
|
||||||
echo "Exiting after unknown error code: %ERRORLEVEL%"
|
|
||||||
exit /b 0
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Validate not sudo
|
|
||||||
user_id=`id -u`
|
|
||||||
if [ $user_id -eq 0 -a -z "$RUNNER_ALLOW_RUNASROOT" ]; then
|
|
||||||
echo "Must not run interactively with sudo"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Run
|
|
||||||
shopt -s nocasematch
|
|
||||||
|
|
||||||
SOURCE="${BASH_SOURCE[0]}"
|
|
||||||
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
|
|
||||||
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
|
|
||||||
SOURCE="$(readlink "$SOURCE")"
|
|
||||||
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
|
|
||||||
done
|
|
||||||
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
|
|
||||||
|
|
||||||
# Wait for docker to start
|
|
||||||
if [ ! -z "$RUNNER_WAIT_FOR_DOCKER_IN_SECONDS" ]; then
|
|
||||||
if [ "$RUNNER_WAIT_FOR_DOCKER_IN_SECONDS" -gt 0 ]; then
|
|
||||||
echo "Waiting for docker to be ready."
|
|
||||||
for i in $(seq "$RUNNER_WAIT_FOR_DOCKER_IN_SECONDS"); do
|
|
||||||
if docker ps > /dev/null 2>&1; then
|
|
||||||
echo "Docker is ready."
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
"$DIR"/safe_sleep.sh 1
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
updateFile="update.finished"
|
|
||||||
"$DIR"/bin/Runner.Listener run $*
|
|
||||||
|
|
||||||
returnCode=$?
|
|
||||||
if [[ $returnCode == 0 ]]; then
|
|
||||||
echo "Runner listener exit with 0 return code, stop the service, no retry needed."
|
|
||||||
exit 0
|
|
||||||
elif [[ $returnCode == 1 ]]; then
|
|
||||||
echo "Runner listener exit with terminated error, stop the service, no retry needed."
|
|
||||||
exit 0
|
|
||||||
elif [[ $returnCode == 2 ]]; then
|
|
||||||
echo "Runner listener exit with retryable error, re-launch runner in 5 seconds."
|
|
||||||
"$DIR"/safe_sleep.sh 5
|
|
||||||
exit 2
|
|
||||||
elif [[ $returnCode == 3 ]]; then
|
|
||||||
# Wait for 30 seconds or for flag file to exists for the runner update process finish
|
|
||||||
echo "Runner listener exit because of updating, re-launch runner after successful update"
|
|
||||||
for i in {0..30}; do
|
|
||||||
if test -f "$updateFile"; then
|
|
||||||
echo "Update finished successfully."
|
|
||||||
rm "$updateFile"
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
"$DIR"/safe_sleep.sh 1
|
|
||||||
done
|
|
||||||
exit 2
|
|
||||||
elif [[ $returnCode == 4 ]]; then
|
|
||||||
# Wait for 30 seconds or for flag file to exists for the ephemeral runner update process finish
|
|
||||||
echo "Runner listener exit because of updating, re-launch runner after successful update"
|
|
||||||
for i in {0..30}; do
|
|
||||||
if test -f "$updateFile"; then
|
|
||||||
echo "Update finished successfully."
|
|
||||||
rm "$updateFile"
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
"$DIR"/safe_sleep.sh 1
|
|
||||||
done
|
|
||||||
exit 2
|
|
||||||
elif [[ $returnCode == 5 ]]; then
|
|
||||||
echo "Runner listener exit with Session Conflict error, stop the service, no retry needed."
|
|
||||||
exit 0
|
|
||||||
else
|
|
||||||
echo "Exiting with unknown error code: ${returnCode}"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
@@ -13,19 +13,21 @@ if defined VERBOSE_ARG (
|
|||||||
rem Unblock files in the root of the layout folder. E.g. .cmd files.
|
rem Unblock files in the root of the layout folder. E.g. .cmd files.
|
||||||
powershell.exe -NoLogo -Sta -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command "$VerbosePreference = %VERBOSE_ARG% ; Get-ChildItem -LiteralPath '%~dp0' | ForEach-Object { Write-Verbose ('Unblock: {0}' -f $_.FullName) ; $_ } | Unblock-File | Out-Null"
|
powershell.exe -NoLogo -Sta -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command "$VerbosePreference = %VERBOSE_ARG% ; Get-ChildItem -LiteralPath '%~dp0' | ForEach-Object { Write-Verbose ('Unblock: {0}' -f $_.FullName) ; $_ } | Unblock-File | Out-Null"
|
||||||
|
|
||||||
|
if /i "%~1" equ "localRun" (
|
||||||
|
rem ********************************************************************************
|
||||||
|
rem Local run.
|
||||||
|
rem ********************************************************************************
|
||||||
|
"%~dp0bin\Runner.Listener.exe" %*
|
||||||
|
) else (
|
||||||
|
rem ********************************************************************************
|
||||||
|
rem Run.
|
||||||
|
rem ********************************************************************************
|
||||||
|
"%~dp0bin\Runner.Listener.exe" run %*
|
||||||
|
|
||||||
rem ********************************************************************************
|
rem Return code 4 means the run once runner received an update message.
|
||||||
rem Run.
|
rem Sleep 5 seconds to wait for the update process finish and run the runner again.
|
||||||
rem ********************************************************************************
|
if ERRORLEVEL 4 (
|
||||||
|
timeout /t 5 /nobreak > NUL
|
||||||
:launch_helper
|
"%~dp0bin\Runner.Listener.exe" run %*
|
||||||
copy "%~dp0run-helper.cmd.template" "%~dp0run-helper.cmd" /Y
|
)
|
||||||
call "%~dp0run-helper.cmd" %*
|
|
||||||
|
|
||||||
if %ERRORLEVEL% EQU 1 (
|
|
||||||
echo "Restarting runner..."
|
|
||||||
goto :launch_helper
|
|
||||||
) else (
|
|
||||||
echo "Exiting runner..."
|
|
||||||
exit /b 0
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,87 +1,51 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Validate not sudo
|
||||||
|
user_id=`id -u`
|
||||||
|
if [ $user_id -eq 0 -a -z "$RUNNER_ALLOW_RUNASROOT" ]; then
|
||||||
|
echo "Must not run interactively with sudo"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Change directory to the script root directory
|
# Change directory to the script root directory
|
||||||
# https://stackoverflow.com/questions/59895/getting-the-source-directory-of-a-bash-script-from-within
|
# https://stackoverflow.com/questions/59895/getting-the-source-directory-of-a-bash-script-from-within
|
||||||
SOURCE="${BASH_SOURCE[0]}"
|
SOURCE="${BASH_SOURCE[0]}"
|
||||||
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
|
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
|
||||||
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
|
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
|
||||||
SOURCE="$(readlink "$SOURCE")"
|
SOURCE="$(readlink "$SOURCE")"
|
||||||
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
|
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
|
||||||
done
|
done
|
||||||
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
|
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
|
||||||
|
|
||||||
run() {
|
# Do not "cd $DIR". For localRun, the current directory is expected to be the repo location on disk.
|
||||||
# run the helper process which keep the listener alive
|
|
||||||
while :;
|
|
||||||
do
|
|
||||||
cp -f "$DIR"/run-helper.sh.template "$DIR"/run-helper.sh
|
|
||||||
"$DIR"/run-helper.sh $*
|
|
||||||
returnCode=$?
|
|
||||||
if [[ $returnCode -eq 2 ]]; then
|
|
||||||
echo "Restarting runner..."
|
|
||||||
else
|
|
||||||
echo "Exiting runner..."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
runWithManualTrap() {
|
# Run
|
||||||
# Set job control
|
shopt -s nocasematch
|
||||||
set -m
|
if [[ "$1" == "localRun" ]]; then
|
||||||
|
"$DIR"/bin/Runner.Listener $*
|
||||||
trap 'kill -INT -$PID' INT TERM
|
|
||||||
|
|
||||||
# run the helper process which keep the listener alive
|
|
||||||
while :;
|
|
||||||
do
|
|
||||||
cp -f "$DIR"/run-helper.sh.template "$DIR"/run-helper.sh
|
|
||||||
"$DIR"/run-helper.sh $* &
|
|
||||||
PID=$!
|
|
||||||
wait $PID
|
|
||||||
returnCode=$?
|
|
||||||
if [[ $returnCode -eq 2 ]]; then
|
|
||||||
echo "Restarting runner..."
|
|
||||||
else
|
|
||||||
echo "Exiting runner..."
|
|
||||||
# Unregister signal handling before exit
|
|
||||||
trap - INT TERM
|
|
||||||
# wait for last parts to be logged
|
|
||||||
wait $PID
|
|
||||||
exit $returnCode
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateCerts() {
|
|
||||||
local sudo_prefix=""
|
|
||||||
local user_id=`id -u`
|
|
||||||
|
|
||||||
if [ $user_id -ne 0 ]; then
|
|
||||||
if [[ ! -x "$(command -v sudo)" ]]; then
|
|
||||||
echo "Warning: failed to update certificate store: sudo is required but not found"
|
|
||||||
return 1
|
|
||||||
else
|
|
||||||
sudo_prefix="sudo"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -x "$(command -v update-ca-certificates)" ]]; then
|
|
||||||
eval $sudo_prefix "update-ca-certificates"
|
|
||||||
elif [[ -x "$(command -v update-ca-trust)" ]]; then
|
|
||||||
eval $sudo_prefix "update-ca-trust"
|
|
||||||
else
|
|
||||||
echo "Warning: failed to update certificate store: update-ca-certificates or update-ca-trust not found. This can happen if you're using a different runner base image."
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
if [[ ! -z "$RUNNER_UPDATE_CA_CERTS" ]]; then
|
|
||||||
updateCerts
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -z "$RUNNER_MANUALLY_TRAP_SIG" ]]; then
|
|
||||||
run $*
|
|
||||||
else
|
else
|
||||||
runWithManualTrap $*
|
"$DIR"/bin/Runner.Listener run $*
|
||||||
|
|
||||||
|
# Return code 4 means the run once runner received an update message.
|
||||||
|
# Sleep 5 seconds to wait for the update process finish and run the runner again.
|
||||||
|
returnCode=$?
|
||||||
|
if [[ $returnCode == 4 ]]; then
|
||||||
|
if [ ! -x "$(command -v sleep)" ]; then
|
||||||
|
if [ ! -x "$(command -v ping)" ]; then
|
||||||
|
COUNT="0"
|
||||||
|
while [[ $COUNT != 5000 ]]; do
|
||||||
|
echo "SLEEP" >nul
|
||||||
|
COUNT=$[$COUNT+1]
|
||||||
|
done
|
||||||
|
else
|
||||||
|
ping -n 5 127.0.0.1 >nul
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
sleep 5 >nul
|
||||||
|
fi
|
||||||
|
|
||||||
|
"$DIR"/bin/Runner.Listener run $*
|
||||||
|
else
|
||||||
|
exit $returnCode
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
SECONDS=0
|
|
||||||
while [[ $SECONDS -lt $1 ]]; do
|
|
||||||
:
|
|
||||||
done
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Common.Util;
|
||||||
|
using GitHub.Runner.Sdk;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
@@ -31,7 +32,7 @@ namespace GitHub.Runner.Common
|
|||||||
new EscapeMapping(token: "%", replacement: "%25"),
|
new EscapeMapping(token: "%", replacement: "%25"),
|
||||||
};
|
};
|
||||||
|
|
||||||
private readonly Dictionary<string, string> _properties = new(StringComparer.OrdinalIgnoreCase);
|
private readonly Dictionary<string, string> _properties = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
public const string Prefix = "##[";
|
public const string Prefix = "##[";
|
||||||
public const string _commandKey = "::";
|
public const string _commandKey = "::";
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
namespace GitHub.Runner.Common
|
using System;
|
||||||
|
|
||||||
|
namespace GitHub.Runner.Common
|
||||||
{
|
{
|
||||||
public enum ActionResult
|
public enum ActionResult
|
||||||
{
|
{
|
||||||
@@ -10,4 +12,4 @@
|
|||||||
|
|
||||||
Skipped = 3
|
Skipped = 3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using GitHub.DistributedTask.Pipelines;
|
|
||||||
using GitHub.DistributedTask.WebApi;
|
|
||||||
using GitHub.Services.Common;
|
|
||||||
using GitHub.Services.WebApi;
|
|
||||||
|
|
||||||
namespace GitHub.Runner.Common
|
|
||||||
{
|
|
||||||
[ServiceLocator(Default = typeof(ActionsRunServer))]
|
|
||||||
public interface IActionsRunServer : IRunnerService
|
|
||||||
{
|
|
||||||
Task ConnectAsync(Uri serverUrl, VssCredentials credentials);
|
|
||||||
|
|
||||||
Task<AgentJobRequestMessage> GetJobMessageAsync(string id, CancellationToken token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class ActionsRunServer : RunnerService, IActionsRunServer
|
|
||||||
{
|
|
||||||
private bool _hasConnection;
|
|
||||||
private VssConnection _connection;
|
|
||||||
private ActionsRunServerHttpClient _actionsRunServerClient;
|
|
||||||
|
|
||||||
public async Task ConnectAsync(Uri serverUrl, VssCredentials credentials)
|
|
||||||
{
|
|
||||||
_connection = await EstablishVssConnection(serverUrl, credentials, TimeSpan.FromSeconds(100));
|
|
||||||
_actionsRunServerClient = _connection.GetClient<ActionsRunServerHttpClient>();
|
|
||||||
_hasConnection = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CheckConnection()
|
|
||||||
{
|
|
||||||
if (!_hasConnection)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"SetConnection");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<AgentJobRequestMessage> GetJobMessageAsync(string id, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
CheckConnection();
|
|
||||||
var jobMessage = RetryRequest<AgentJobRequestMessage>(async () =>
|
|
||||||
{
|
|
||||||
return await _actionsRunServerClient.GetJobMessageAsync(id, cancellationToken);
|
|
||||||
}, cancellationToken);
|
|
||||||
|
|
||||||
return jobMessage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace GitHub.Runner.Common
|
|
||||||
{
|
|
||||||
public class AuthMigrationEventArgs : EventArgs
|
|
||||||
{
|
|
||||||
public AuthMigrationEventArgs(string trace)
|
|
||||||
{
|
|
||||||
Trace = trace;
|
|
||||||
}
|
|
||||||
public string Trace { get; private set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using GitHub.Actions.RunService.WebApi;
|
|
||||||
using GitHub.DistributedTask.Pipelines;
|
|
||||||
using GitHub.DistributedTask.WebApi;
|
|
||||||
using GitHub.Runner.Sdk;
|
|
||||||
using GitHub.Services.Common;
|
|
||||||
using GitHub.Services.WebApi;
|
|
||||||
using Sdk.RSWebApi.Contracts;
|
|
||||||
using Sdk.WebApi.WebApi.RawClient;
|
|
||||||
|
|
||||||
namespace GitHub.Runner.Common
|
|
||||||
{
|
|
||||||
[ServiceLocator(Default = typeof(BrokerServer))]
|
|
||||||
public interface IBrokerServer : IRunnerService
|
|
||||||
{
|
|
||||||
Task ConnectAsync(Uri serverUrl, VssCredentials credentials);
|
|
||||||
|
|
||||||
Task<TaskAgentSession> CreateSessionAsync(TaskAgentSession session, CancellationToken cancellationToken);
|
|
||||||
Task DeleteSessionAsync(CancellationToken cancellationToken);
|
|
||||||
|
|
||||||
Task<TaskAgentMessage> GetRunnerMessageAsync(Guid? sessionId, TaskAgentStatus status, string version, string os, string architecture, bool disableUpdate, CancellationToken token);
|
|
||||||
|
|
||||||
Task AcknowledgeRunnerRequestAsync(string runnerRequestId, Guid? sessionId, TaskAgentStatus status, string version, string os, string architecture, CancellationToken token);
|
|
||||||
|
|
||||||
Task UpdateConnectionIfNeeded(Uri serverUri, VssCredentials credentials);
|
|
||||||
|
|
||||||
Task ForceRefreshConnection(VssCredentials credentials);
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class BrokerServer : RunnerService, IBrokerServer
|
|
||||||
{
|
|
||||||
private bool _hasConnection;
|
|
||||||
private Uri _brokerUri;
|
|
||||||
private RawConnection _connection;
|
|
||||||
private BrokerHttpClient _brokerHttpClient;
|
|
||||||
|
|
||||||
public async Task ConnectAsync(Uri serverUri, VssCredentials credentials)
|
|
||||||
{
|
|
||||||
Trace.Entering();
|
|
||||||
_brokerUri = serverUri;
|
|
||||||
|
|
||||||
_connection = VssUtil.CreateRawConnection(serverUri, credentials);
|
|
||||||
_brokerHttpClient = await _connection.GetClientAsync<BrokerHttpClient>();
|
|
||||||
_hasConnection = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CheckConnection()
|
|
||||||
{
|
|
||||||
if (!_hasConnection)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"SetConnection");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<TaskAgentSession> CreateSessionAsync(TaskAgentSession session, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
CheckConnection();
|
|
||||||
var jobMessage = await _brokerHttpClient.CreateSessionAsync(session, cancellationToken);
|
|
||||||
|
|
||||||
return jobMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<TaskAgentMessage> GetRunnerMessageAsync(Guid? sessionId, TaskAgentStatus status, string version, string os, string architecture, bool disableUpdate, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
CheckConnection();
|
|
||||||
var brokerSession = RetryRequest<TaskAgentMessage>(
|
|
||||||
async () => await _brokerHttpClient.GetRunnerMessageAsync(sessionId, version, status, os, architecture, disableUpdate, cancellationToken), cancellationToken, shouldRetry: ShouldRetryException);
|
|
||||||
|
|
||||||
return brokerSession;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task AcknowledgeRunnerRequestAsync(string runnerRequestId, Guid? sessionId, TaskAgentStatus status, string version, string os, string architecture, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
CheckConnection();
|
|
||||||
|
|
||||||
// No retries
|
|
||||||
await _brokerHttpClient.AcknowledgeRunnerRequestAsync(runnerRequestId, sessionId, version, status, os, architecture, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DeleteSessionAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
CheckConnection();
|
|
||||||
await _brokerHttpClient.DeleteSessionAsync(cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task UpdateConnectionIfNeeded(Uri serverUri, VssCredentials credentials)
|
|
||||||
{
|
|
||||||
if (_brokerUri != serverUri || !_hasConnection)
|
|
||||||
{
|
|
||||||
return ConnectAsync(serverUri, credentials);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task ForceRefreshConnection(VssCredentials credentials)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(_brokerUri?.AbsoluteUri))
|
|
||||||
{
|
|
||||||
return ConnectAsync(_brokerUri, credentials);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ShouldRetryException(Exception ex)
|
|
||||||
{
|
|
||||||
if (ex is AccessDeniedException || ex is RunnerNotFoundException || ex is HostedRunnerDeprovisionedException)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using GitHub.Runner.Common.Util;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using GitHub.DistributedTask.Logging;
|
using GitHub.DistributedTask.Logging;
|
||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
using System;
|
using GitHub.Runner.Common.Util;
|
||||||
|
using GitHub.Runner.Sdk;
|
||||||
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using GitHub.Runner.Sdk;
|
|
||||||
|
|
||||||
namespace GitHub.Runner.Common
|
namespace GitHub.Runner.Common
|
||||||
{
|
{
|
||||||
@@ -18,7 +19,7 @@ namespace GitHub.Runner.Common
|
|||||||
private bool? _isHostedServer;
|
private bool? _isHostedServer;
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
[DataMember(EmitDefaultValue = false)]
|
||||||
public ulong AgentId { get; set; }
|
public int AgentId { get; set; }
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
[DataMember(EmitDefaultValue = false)]
|
||||||
public string AgentName { get; set; }
|
public string AgentName { get; set; }
|
||||||
@@ -32,12 +33,6 @@ namespace GitHub.Runner.Common
|
|||||||
[DataMember(EmitDefaultValue = false)]
|
[DataMember(EmitDefaultValue = false)]
|
||||||
public string PoolName { get; set; }
|
public string PoolName { get; set; }
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public bool DisableUpdate { get; set; }
|
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public bool Ephemeral { get; set; }
|
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
[DataMember(EmitDefaultValue = false)]
|
||||||
public string ServerUrl { get; set; }
|
public string ServerUrl { get; set; }
|
||||||
|
|
||||||
@@ -50,34 +45,13 @@ namespace GitHub.Runner.Common
|
|||||||
[DataMember(EmitDefaultValue = false)]
|
[DataMember(EmitDefaultValue = false)]
|
||||||
public string MonitorSocketAddress { get; set; }
|
public string MonitorSocketAddress { get; set; }
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public bool UseV2Flow { get; set; }
|
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public bool UseRunnerAdminFlow { get; set; }
|
|
||||||
|
|
||||||
[DataMember(EmitDefaultValue = false)]
|
|
||||||
public string ServerUrlV2 { get; set; }
|
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsHostedServer
|
public bool IsHostedServer
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
// If the value has been explicitly set, return it.
|
// Old runners do not have this property. Hosted runners likely don't have this property either.
|
||||||
if (_isHostedServer.HasValue)
|
return _isHostedServer ?? true;
|
||||||
{
|
|
||||||
return _isHostedServer.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, try to infer it from the GitHubUrl.
|
|
||||||
if (!string.IsNullOrEmpty(GitHubUrl))
|
|
||||||
{
|
|
||||||
return UrlUtil.IsHostedServer(new UriBuilder(GitHubUrl));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default to true since Hosted runners likely don't have this property set.
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set
|
set
|
||||||
@@ -95,18 +69,17 @@ namespace GitHub.Runner.Common
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
Uri accountUri = new(this.ServerUrl);
|
Uri accountUri = new Uri(this.ServerUrl);
|
||||||
string repoOrOrgName = string.Empty;
|
string repoOrOrgName = string.Empty;
|
||||||
|
|
||||||
if (accountUri.Host.EndsWith(".githubusercontent.com", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(this.GitHubUrl))
|
if (accountUri.Host.EndsWith(".githubusercontent.com", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
Uri gitHubUrl = new(this.GitHubUrl);
|
Uri gitHubUrl = new Uri(this.GitHubUrl);
|
||||||
|
|
||||||
// Use the "NWO part" from the GitHub URL path
|
// Use the "NWO part" from the GitHub URL path
|
||||||
repoOrOrgName = gitHubUrl.AbsolutePath.Trim('/');
|
repoOrOrgName = gitHubUrl.AbsolutePath.Trim('/');
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (string.IsNullOrEmpty(repoOrOrgName))
|
|
||||||
{
|
{
|
||||||
repoOrOrgName = accountUri.AbsolutePath.Split('/', StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
|
repoOrOrgName = accountUri.AbsolutePath.Split('/', StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
|
||||||
}
|
}
|
||||||
@@ -131,15 +104,11 @@ namespace GitHub.Runner.Common
|
|||||||
bool IsConfigured();
|
bool IsConfigured();
|
||||||
bool IsServiceConfigured();
|
bool IsServiceConfigured();
|
||||||
bool HasCredentials();
|
bool HasCredentials();
|
||||||
bool IsMigratedConfigured();
|
|
||||||
CredentialData GetCredentials();
|
CredentialData GetCredentials();
|
||||||
CredentialData GetMigratedCredentials();
|
CredentialData GetMigratedCredentials();
|
||||||
RunnerSettings GetSettings();
|
RunnerSettings GetSettings();
|
||||||
RunnerSettings GetMigratedSettings();
|
|
||||||
void SaveCredential(CredentialData credential);
|
void SaveCredential(CredentialData credential);
|
||||||
void SaveMigratedCredential(CredentialData credential);
|
|
||||||
void SaveSettings(RunnerSettings settings);
|
void SaveSettings(RunnerSettings settings);
|
||||||
void SaveMigratedSettings(RunnerSettings settings);
|
|
||||||
void DeleteCredential();
|
void DeleteCredential();
|
||||||
void DeleteMigratedCredential();
|
void DeleteMigratedCredential();
|
||||||
void DeleteSettings();
|
void DeleteSettings();
|
||||||
@@ -149,7 +118,6 @@ namespace GitHub.Runner.Common
|
|||||||
{
|
{
|
||||||
private string _binPath;
|
private string _binPath;
|
||||||
private string _configFilePath;
|
private string _configFilePath;
|
||||||
private string _migratedConfigFilePath;
|
|
||||||
private string _credFilePath;
|
private string _credFilePath;
|
||||||
private string _migratedCredFilePath;
|
private string _migratedCredFilePath;
|
||||||
private string _serviceConfigFilePath;
|
private string _serviceConfigFilePath;
|
||||||
@@ -157,7 +125,6 @@ namespace GitHub.Runner.Common
|
|||||||
private CredentialData _creds;
|
private CredentialData _creds;
|
||||||
private CredentialData _migratedCreds;
|
private CredentialData _migratedCreds;
|
||||||
private RunnerSettings _settings;
|
private RunnerSettings _settings;
|
||||||
private RunnerSettings _migratedSettings;
|
|
||||||
|
|
||||||
public override void Initialize(IHostContext hostContext)
|
public override void Initialize(IHostContext hostContext)
|
||||||
{
|
{
|
||||||
@@ -175,9 +142,6 @@ namespace GitHub.Runner.Common
|
|||||||
_configFilePath = hostContext.GetConfigFile(WellKnownConfigFile.Runner);
|
_configFilePath = hostContext.GetConfigFile(WellKnownConfigFile.Runner);
|
||||||
Trace.Info("ConfigFilePath: {0}", _configFilePath);
|
Trace.Info("ConfigFilePath: {0}", _configFilePath);
|
||||||
|
|
||||||
_migratedConfigFilePath = hostContext.GetConfigFile(WellKnownConfigFile.MigratedRunner);
|
|
||||||
Trace.Info("MigratedConfigFilePath: {0}", _migratedConfigFilePath);
|
|
||||||
|
|
||||||
_credFilePath = hostContext.GetConfigFile(WellKnownConfigFile.Credentials);
|
_credFilePath = hostContext.GetConfigFile(WellKnownConfigFile.Credentials);
|
||||||
Trace.Info("CredFilePath: {0}", _credFilePath);
|
Trace.Info("CredFilePath: {0}", _credFilePath);
|
||||||
|
|
||||||
@@ -193,7 +157,7 @@ namespace GitHub.Runner.Common
|
|||||||
public bool HasCredentials()
|
public bool HasCredentials()
|
||||||
{
|
{
|
||||||
Trace.Info("HasCredentials()");
|
Trace.Info("HasCredentials()");
|
||||||
bool credsStored = new FileInfo(_credFilePath).Exists || new FileInfo(_migratedCredFilePath).Exists;
|
bool credsStored = (new FileInfo(_credFilePath)).Exists || (new FileInfo(_migratedCredFilePath)).Exists;
|
||||||
Trace.Info("stored {0}", credsStored);
|
Trace.Info("stored {0}", credsStored);
|
||||||
return credsStored;
|
return credsStored;
|
||||||
}
|
}
|
||||||
@@ -201,7 +165,7 @@ namespace GitHub.Runner.Common
|
|||||||
public bool IsConfigured()
|
public bool IsConfigured()
|
||||||
{
|
{
|
||||||
Trace.Info("IsConfigured()");
|
Trace.Info("IsConfigured()");
|
||||||
bool configured = new FileInfo(_configFilePath).Exists || new FileInfo(_migratedConfigFilePath).Exists;
|
bool configured = new FileInfo(_configFilePath).Exists;
|
||||||
Trace.Info("IsConfigured: {0}", configured);
|
Trace.Info("IsConfigured: {0}", configured);
|
||||||
return configured;
|
return configured;
|
||||||
}
|
}
|
||||||
@@ -209,19 +173,11 @@ namespace GitHub.Runner.Common
|
|||||||
public bool IsServiceConfigured()
|
public bool IsServiceConfigured()
|
||||||
{
|
{
|
||||||
Trace.Info("IsServiceConfigured()");
|
Trace.Info("IsServiceConfigured()");
|
||||||
bool serviceConfigured = new FileInfo(_serviceConfigFilePath).Exists;
|
bool serviceConfigured = (new FileInfo(_serviceConfigFilePath)).Exists;
|
||||||
Trace.Info($"IsServiceConfigured: {serviceConfigured}");
|
Trace.Info($"IsServiceConfigured: {serviceConfigured}");
|
||||||
return serviceConfigured;
|
return serviceConfigured;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsMigratedConfigured()
|
|
||||||
{
|
|
||||||
Trace.Info("IsMigratedConfigured()");
|
|
||||||
bool configured = new FileInfo(_migratedConfigFilePath).Exists;
|
|
||||||
Trace.Info("IsMigratedConfigured: {0}", configured);
|
|
||||||
return configured;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CredentialData GetCredentials()
|
public CredentialData GetCredentials()
|
||||||
{
|
{
|
||||||
if (_creds == null)
|
if (_creds == null)
|
||||||
@@ -261,25 +217,6 @@ namespace GitHub.Runner.Common
|
|||||||
return _settings;
|
return _settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RunnerSettings GetMigratedSettings()
|
|
||||||
{
|
|
||||||
if (_migratedSettings == null)
|
|
||||||
{
|
|
||||||
RunnerSettings configuredSettings = null;
|
|
||||||
if (File.Exists(_migratedConfigFilePath))
|
|
||||||
{
|
|
||||||
string json = File.ReadAllText(_migratedConfigFilePath, Encoding.UTF8);
|
|
||||||
Trace.Info($"Read migrated setting file: {json.Length} chars");
|
|
||||||
configuredSettings = StringUtil.ConvertFromJson<RunnerSettings>(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
ArgUtil.NotNull(configuredSettings, nameof(configuredSettings));
|
|
||||||
_migratedSettings = configuredSettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _migratedSettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SaveCredential(CredentialData credential)
|
public void SaveCredential(CredentialData credential)
|
||||||
{
|
{
|
||||||
Trace.Info("Saving {0} credential @ {1}", credential.Scheme, _credFilePath);
|
Trace.Info("Saving {0} credential @ {1}", credential.Scheme, _credFilePath);
|
||||||
@@ -295,21 +232,6 @@ namespace GitHub.Runner.Common
|
|||||||
File.SetAttributes(_credFilePath, File.GetAttributes(_credFilePath) | FileAttributes.Hidden);
|
File.SetAttributes(_credFilePath, File.GetAttributes(_credFilePath) | FileAttributes.Hidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SaveMigratedCredential(CredentialData credential)
|
|
||||||
{
|
|
||||||
Trace.Info("Saving {0} migrated credential @ {1}", credential.Scheme, _migratedCredFilePath);
|
|
||||||
if (File.Exists(_migratedCredFilePath))
|
|
||||||
{
|
|
||||||
// Delete existing credential file first, since the file is hidden and not able to overwrite.
|
|
||||||
Trace.Info("Delete exist runner migrated credential file.");
|
|
||||||
IOUtil.DeleteFile(_migratedCredFilePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
IOUtil.SaveObject(credential, _migratedCredFilePath);
|
|
||||||
Trace.Info("Migrated Credentials Saved.");
|
|
||||||
File.SetAttributes(_migratedCredFilePath, File.GetAttributes(_migratedCredFilePath) | FileAttributes.Hidden);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SaveSettings(RunnerSettings settings)
|
public void SaveSettings(RunnerSettings settings)
|
||||||
{
|
{
|
||||||
Trace.Info("Saving runner settings.");
|
Trace.Info("Saving runner settings.");
|
||||||
@@ -325,21 +247,6 @@ namespace GitHub.Runner.Common
|
|||||||
File.SetAttributes(_configFilePath, File.GetAttributes(_configFilePath) | FileAttributes.Hidden);
|
File.SetAttributes(_configFilePath, File.GetAttributes(_configFilePath) | FileAttributes.Hidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SaveMigratedSettings(RunnerSettings settings)
|
|
||||||
{
|
|
||||||
Trace.Info("Saving runner migrated settings");
|
|
||||||
if (File.Exists(_migratedConfigFilePath))
|
|
||||||
{
|
|
||||||
// Delete existing settings file first, since the file is hidden and not able to overwrite.
|
|
||||||
Trace.Info("Delete exist runner migrated settings file.");
|
|
||||||
IOUtil.DeleteFile(_migratedConfigFilePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
IOUtil.SaveObject(settings, _migratedConfigFilePath);
|
|
||||||
Trace.Info("Migrated Settings Saved.");
|
|
||||||
File.SetAttributes(_migratedConfigFilePath, File.GetAttributes(_migratedConfigFilePath) | FileAttributes.Hidden);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DeleteCredential()
|
public void DeleteCredential()
|
||||||
{
|
{
|
||||||
IOUtil.Delete(_credFilePath, default(CancellationToken));
|
IOUtil.Delete(_credFilePath, default(CancellationToken));
|
||||||
@@ -354,12 +261,6 @@ namespace GitHub.Runner.Common
|
|||||||
public void DeleteSettings()
|
public void DeleteSettings()
|
||||||
{
|
{
|
||||||
IOUtil.Delete(_configFilePath, default(CancellationToken));
|
IOUtil.Delete(_configFilePath, default(CancellationToken));
|
||||||
IOUtil.Delete(_migratedConfigFilePath, default(CancellationToken));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DeleteMigratedSettings()
|
|
||||||
{
|
|
||||||
IOUtil.Delete(_migratedConfigFilePath, default(CancellationToken));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user