Merge pull request #21 from GitHubSecurityLab/refactor_env_access

refactor env access
This commit is contained in:
Alvaro Muñoz
2024-02-26 13:02:33 +01:00
committed by GitHub
5 changed files with 359 additions and 66 deletions

View File

@@ -23,6 +23,21 @@ class AstNode instanceof YamlNode {
class Statement extends AstNode {
/** Gets the workflow that this job is a part of. */
WorkflowStmt getEnclosingWorkflowStmt() { this = result.getAChildNode*() }
/**
* Gets a environment variable expression by name in the scope of the current step.
*/
Expression getEnvExpr(string name) {
exists(Actions::Env env |
env.(YamlMapping).maps(any(YamlScalar s | s.getValue() = name), result)
|
env.(Actions::StepEnv).getStep().getAChildNode*() = this
or
env.(Actions::JobEnv).getJob().getAChildNode*() = this
or
env.(Actions::WorkflowEnv).getWorkflow().getAChildNode*() = this
)
}
}
/**
@@ -212,8 +227,6 @@ abstract class UsesExpr extends Expression {
abstract string getVersion();
abstract Expression getArgumentExpr(string key);
abstract Expression getEnvExpr(string name);
}
/**
@@ -234,26 +247,6 @@ class StepUsesExpr extends StepStmt, UsesExpr {
result = with.lookup(key)
)
}
/**
* Gets a environment variable expression by name in the scope of the current step.
*/
override Expression getEnvExpr(string name) {
exists(Actions::StepEnv env |
env.getStep() = this and
env.(YamlMapping).maps(any(YamlScalar s | s.getValue() = name), result)
)
or
exists(Actions::JobEnv env |
env.getJob() = this.getJobStmt() and
env.(YamlMapping).maps(any(YamlScalar s | s.getValue() = name), result)
)
or
exists(Actions::WorkflowEnv env |
env.getWorkflow() = this.getJobStmt().getEnclosingWorkflowStmt() and
env.(YamlMapping).maps(any(YamlScalar s | s.getValue() = name), result)
)
}
}
/**
@@ -302,23 +295,6 @@ class JobUsesExpr extends UsesExpr instanceof YamlMapping {
override Expression getArgumentExpr(string key) {
this.(YamlMapping).lookup("with").(YamlMapping).lookup(key) = result
}
/**
* Gets a environment variable expression by name in the scope of the current node.
*/
override Expression getEnvExpr(string name) {
this.(YamlMapping).lookup("env").(YamlMapping).lookup(name) = result
or
exists(Actions::JobEnv env |
env.getJob() = this.getJobStmt() and
env.(YamlMapping).maps(any(YamlScalar s | s.getValue() = name), result)
)
or
exists(Actions::WorkflowEnv env |
env.getWorkflow() = this.getJobStmt().getEnclosingWorkflowStmt() and
env.(YamlMapping).maps(any(YamlScalar s | s.getValue() = name), result)
)
}
}
/**
@@ -332,26 +308,6 @@ class RunExpr extends StepStmt, Expression {
Expression getScriptExpr() { result = scriptExpr }
string getScript() { result = scriptExpr.getValue() }
/**
* Gets a environment variable expression by name in the scope of the current node.
*/
Expression getEnvExpr(string name) {
exists(Actions::StepEnv env |
env.getStep() = this and
env.(YamlMapping).maps(any(YamlScalar s | s.getValue() = name), result)
)
or
exists(Actions::JobEnv env |
env.getJob() = this.getJobStmt() and
env.(YamlMapping).maps(any(YamlScalar s | s.getValue() = name), result)
)
or
exists(Actions::WorkflowEnv env |
env.getWorkflow() = this.getJobStmt().getEnclosingWorkflowStmt() and
env.(YamlMapping).maps(any(YamlScalar s | s.getValue() = name), result)
)
}
}
/**
@@ -523,11 +479,9 @@ class EnvCtxAccessExpr extends CtxAccessExpr {
override string getFieldName() { result = fieldName }
override Expression getRefExpr() {
result.getLocation().getFile() = this.getLocation().getFile() and
exists(JobUsesExpr s | s.getEnvExpr(fieldName) = result)
or
exists(StepUsesExpr s | s.getEnvExpr(fieldName) = result)
or
exists(RunExpr s | s.getEnvExpr(fieldName) = result)
exists(Statement s |
s.getEnvExpr(fieldName) = result and
s.getAChildNode*() = this
)
}
}

View File

@@ -25,7 +25,10 @@ class ActorCheckStmt extends IfStmt {
* An If node that contains a `label` check
*/
class LabelCheckStmt extends IfStmt {
LabelCheckStmt() { this.getCondition().regexpMatch(".*github\\.event\\.pull_request\\.labels.*") }
LabelCheckStmt() {
this.getCondition().regexpMatch(".*github\\.event\\.pull_request\\.labels.*") or
this.getCondition().regexpMatch(".*github\\.event\\.label\\.name.*")
}
}
from WorkflowStmt w, JobStmt job, StepUsesExpr checkoutStep

160
ql/src/test/.github/workflows/cross1.yml vendored Normal file
View File

@@ -0,0 +1,160 @@
# Issues_workflow.yaml (https://github.com/Bughalla/dynamods_dynamo/blob/1c1d3e29ee9bca81b43d78f22bf953100ef67009/.github/workflows/Issues_workflow.yaml#L128-L128)
name: Issue Workflow
on:
issues:
types: [opened,edited]
jobs:
#This job will check the issue to determine if it should be moved to a different repository
redirectIssue:
name: Check for issue transfer
runs-on: ubuntu-latest
env:
#The 'content_analysis_response' variable is used to store the script response on step one,
#and then checked on step two to know if adding any labels is necessary.
#The initial 'undefined' value will be overridden when the script runs.
content_analysis_response: undefined
ISSUE_TITLE: ${{github.event.issue.title}}
ISSUE_BODY: ${{github.event.issue.body}}
outputs:
result: ${{env.content_analysis_response}}
steps:
- uses: actions/checkout@v4
#Detect if the issue_title follows the regex expression
- name: Check Issue Title
uses: actions-ecosystem/action-regex-match@v2
id: regex-match
with:
text: ${{github.event.issue.title}}
regex: '^[A-Za-z0-9 _.]*$'
flags: g
#If the regex output is '' means that the issue title contains special chars
- name: Exit Job
if: ${{ steps.regex-match.outputs.match == '' }}
run: |
echo "Bad Issue Title Format"
exit 1
#Remove the " character in the issue title and replaced with -
- name: Remove conflicting chars
uses: frabert/replace-string-action@v2.5
id: remove_quotations
with:
pattern: "\""
string: ${{env.ISSUE_TITLE}}
replace-with: '-'
flags: g
#According to the issue_title returns a specific label
- name: Check Information
id: check-info
env:
ISSUE_TITLE_PARSED: ${{steps.remove_quotations.outputs.replaced}}
run: |
echo "content_analysis_response=$(pwsh .\\.github\\scripts\\title_analyzer.ps1)" >> $GITHUB_ENV
#labels the issue based in the text returned in content_analysis_response var
- name: Label issue
if: env.content_analysis_response != 'Valid'
#Uses DYNAMOBOTTOKEN to allow interaction between repos
run: |
curl -v -u admin:${{ secrets.DYNAMOBOTTOKEN }} -d '{"labels": ["${{env.content_analysis_response}}"]}' ${{ github.event.issue.url }}/labels
#This job will scan the issue content to determing if more information is needed and act acordingly
#Will only run if the "redirectIssue" job outputted a 'Valid' result
checkIssueInformation:
if: needs.redirectIssue.outputs.result == 'Valid'
name: Check for missing information
#Wait for the previous job to finish as it needs its output
needs: redirectIssue
runs-on: ubuntu-latest
env:
#The 'analysis_response' variable is used to store the script response on step one,
#and then checked on step two to know if adding the label and comment is necessary.
#The initial 'undefined' value will be overridden when the script runs.
analysis_response: undefined
#Greetings for valid issues
greetings_comment: "Thank you for submitting the issue to us. We are sorry to
see you get stuck with your workflow. While waiting for our team member to respond,
please feel free to browse our forum at https://forum.dynamobim.com/ for more Dynamo related information."
#Comment intro
comment_intro: "Hello ${{ github.actor }}, thank you for submitting this issue!
We are super excited that you want to help us make Dynamo all that it can be."
#issue_coment holds the comment format, while the missing information will be provided by analysis_response
needs_more_info_comment: "However, we need some more information in order for the Dynamo
team to investigate any further.\\n\\n"
#comment to be used if the issue is closed due to the template being empty
close_issue_comment: "However, given that there has been no additional information added,
this issue will be closed for now. Please reopen and provide additional
information if you wish the Dynamo team to investigate further.\\n\\n"
#Info asked from the user in bot comments
info_needed: "Additional information:\\n
- Filling in of the provided Template (What did you do, What did you expect to see,
What did you see instead, What packages or external references (if any) were used)\\n
- Attaching the Stack Trace (Error message that shows up when Dynamo crashes - You can copy and paste this into the Github Issue)\\n
- Upload a .DYN file that showcases the issue in action and any additional needed files, such as Revit
(Note: If you cannot share a project, you can recreate this in a quick mock-up file)\\n
- Upload a Screenshot of the error messages you see (Hover over the offending node and showcase
said errors message in the screenshot)\\n
- Reproducible steps on how to create the error in question."
#Text to ask for specific missing information (complemented by the analysis response)
specific_info: "Can you please fill in the following to the best of your ability:"
#template file name
template: "ISSUE_TEMPLATE.md"
#label to tag the issue with if its missing information
issue_label: needs more info
#amount of sections from the template that can be missing information for the issue to still be considered complete
acceptable_missing_info: 1
steps:
#Checkout the repo
- uses: actions/checkout@v4
#Removes conflicting characters before using the issue content as a script parameter
- name: Remove conflicting chars
env:
ISSUE_BODY: ${{github.event.issue.body}}
uses: frabert/replace-string-action@v2.5
id: remove_quotations
with:
pattern: "\""
string: ${{env.ISSUE_BODY}}
replace-with: '-'
flags: g
#Checks for missing information inside the issue content
- name: Check Information
id: check-info
env:
ISSUE_BODY: ${{ steps.remove_quotations.outputs.replaced }}
run: |
echo "analysis_response=$(pwsh .\\.github\\scripts\\issue_analyzer.ps1 "${{ env.template }}" "${{ env.acceptable_missing_info }}" )" >> $GITHUB_ENV
#Closes the issue if the analysis response is "Empty"
- name: Close issue
if: env.analysis_response == 'Empty'
run: |
curl -v -u admin:${{ secrets.GITHUB_TOKEN }} -d '{"body": "${{env.comment_intro}} ${{env.close_issue_comment}} ${{env.info_needed}}"}' ${{ github.event.issue.url }}/comments
curl -v -u admin:${{ secrets.GITHUB_TOKEN }} -X PATCH -d '{"state": "closed"}' ${{ github.event.issue.url }}
#Adds the "needs more info" label if needed
- name: Label and comment issue
if: ((env.analysis_response != 'Valid') && (env.analysis_response != 'Empty') && (github.event.action == 'opened'))
run: |
curl -v -u admin:${{ secrets.GITHUB_TOKEN }} -d '{"labels": ["${{env.issue_label}}"]}' ${{ github.event.issue.url }}/labels
curl -v -u admin:${{ secrets.GITHUB_TOKEN }} -d '{"body": "${{env.comment_intro}} ${{env.needs_more_info_comment}} ${{env.specific_info}} ${{env.analysis_response}}.\n\n${{env.info_needed}}"}' ${{ github.event.issue.url }}/comments
#Removes the "needs more info" label if the issue has the missing information
- name: Unlabel updated issue
if: env.analysis_response == 'Valid' && github.event.action == 'edited'
run: |
echo urldecode ${{env.issue_label}}
curl -v -u admin:${{ secrets.GITHUB_TOKEN }} -X DELETE ${{ github.event.issue.url }}/labels/$(echo -ne "${{env.issue_label}}" | xxd -plain | tr -d '\n' | sed 's/\(..\)/%\1/g')
#Adds greetings message
- name: Greetings
if: env.analysis_response == 'Valid' && github.event.action == 'opened'
run: |
curl -v -u admin:${{ secrets.GITHUB_TOKEN }} -d '{"body": "${{env.greetings_comment}}"}' ${{ github.event.issue.url }}/comments

109
ql/src/test/.github/workflows/cross2.yml vendored Normal file
View File

@@ -0,0 +1,109 @@
# issue_type_predicter.yml (https://github.com/Bughalla/dynamods_dynamo/blob/1c1d3e29ee9bca81b43d78f22bf953100ef67009/.github/workflows/issue_type_predicter.yml#L40-L40)
name: Issue Type Predicter
# This workflow uses https://github.com/DynamoDS/IssuesTypePredicter to predict the type of a github issue
on:
issues:
types: [opened, edited]
jobs:
issue_type_Predicter:
name: Issue Type Predicter
runs-on: ubuntu-latest
env:
# The 'analysis_response' variable is used to store the response returned by issue_analyzer.ps1
# The initial 'undefined' value will be overridden when the script runs
analysis_response: undefined
# The 'parsed_issue_body' variable is used to store the parsed issue body (after removing some sections of the body like Stack Trace)
parsed_issue_body: undefined
# The 'issue_json_string' variable is used to store parsed info of the issue body as a json string
issue_json_string: undefined
# The 'is_wish_list' variable is used to store the value returned by the IssuesTypePredicter project
is_wish_list: undefined
# issue template file name
template: "ISSUE_TEMPLATE.md"
# amount of sections from the template that can be missing information for the issue to still be considered valid
acceptable_missing_info: 1
steps:
# Checkout Dynamo repo
- name: Checkout Dynamo Repo
uses: actions/checkout@v4
# Removes quotes before using the issue content as a script parameter
- name: Remove Quotes
id: remove_quotes
uses: frabert/replace-string-action@v2.5
env:
ISSUE_BODY: ${{ github.event.issue.body }}
with:
pattern: "\""
string: ${{ env.ISSUE_BODY }}
replace-with: '-'
# Analyze for missing information inside the issue content
- name: Analyze Issue Body
env:
ISSUE_BODY: ${{ steps.remove_quotes.outputs.replaced }}
run: |
echo "analysis_response=$(pwsh .\\.github\\scripts\\issue_analyzer.ps1 "${{ env.template }}" "${{ env.acceptable_missing_info }}")" >> $GITHUB_ENV
# Remove sections in the issue body like "Dynamo version", "Stack Trace" because won't be used to predict the issue type
- name: Clean Issue Body
if: env.analysis_response == 'Valid'
env:
ISSUE_BODY_PARSED: ${{ steps.remove_quotes.outputs.replaced }}
run: |
echo "parsed_issue_body="$(pwsh .\\.github\\scripts\\issue_body_cleaner.ps1 )"" >> $GITHUB_ENV
# Create json string from the issue body
- name: Create Issue JSON String
if: env.analysis_response == 'Valid'
env:
ISSUE_NUMBER: ${{ github.event.issue.number }}
ISSUE_TITLE: ${{ github.event.issue.title }}
run: |
echo "issue_json_string="$(pwsh .\\.github\\scripts\\get_issue_json_body.ps1 "$ISSUE_NUMBER")"" >> $GITHUB_ENV
# Checkout the IssuesTypePredicter repo (https://github.com/DynamoDS/IssuesTypePredicter)
- name: Checkout IssuesTypePredicter Repo
if: env.analysis_response == 'Valid'
uses: actions/checkout@v4
with:
repository: DynamoDS/IssuesTypePredicter
path: IssuesTypePredicter
# Setup dotnet
- name: Setup dotnet
uses: actions/setup-dotnet@v4
with:
dotnet-version: '3.1.0'
# Build the solution IssuesTypePredicter.sln (this contains two VS2019 ML.NET projects)
- name: Build Issues Type Predicter
if: env.analysis_response == 'Valid'
run: |
dotnet build ./IssuesTypePredicter/IssuesTypePredicter.sln --configuration Release
cp ./IssuesTypePredicter/IssuesTypePredicterML.ConsoleApp/bin/Release/netcoreapp3.1/MLModel.zip .
# Execute the IssuesTypePredicter program and pass 'issue_json_string' as a parameter
- name: Run Issues Type Predicter
if: env.analysis_response == 'Valid'
run: |
echo "is_wish_list="$(dotnet run -p ./IssuesTypePredicter/IssuesTypePredicterML.ConsoleApp/IssuesTypePredicterML.ConsoleApp.csproj -v q "${{ env.issue_json_string }}")"" >> $GITHUB_ENV
# If the is_wish_list variable contains 1, label the issue as "Wishlist"
- name: Label issue as 'Wishlist'
if: env.analysis_response == 'Valid' && contains(env.is_wish_list, 'IsWishlist:1')
env:
GH_TOKEN: ${{ secrets.DYNAMO_ISSUES_TOKEN }}
run: |
gh issue edit ${{ github.event.issue.number }} --add-label "Wishlist" --repo ${{ github.repository }}
# If the issue is missing important information (don't follow the template structure), label the issue as "NotMLEvaluated"
- name: Label issue as 'NotMLEvaluated'
if: env.analysis_response != 'Valid' || env.issue_json_string == ''
env:
GH_TOKEN: ${{ secrets.DYNAMO_ISSUES_TOKEN }}
run: |
gh issue edit ${{ github.event.issue.number }} --add-label "NotMLEvaluated" --repo ${{ github.repository }}

View File

@@ -0,0 +1,67 @@
# cherry-picking.yaml (https://github.com/Bughalla/dynamods_dynamo/blob/1c1d3e29ee9bca81b43d78f22bf953100ef67009/.github/workflows/disabled/cherry-picking.yaml#L45-L51)
#DYN-3364
#This action is disabled for now due to it not behaving as expected
name: Cherry picking
on:
push:
branches:
- master
jobs:
cherry_pick:
runs-on: ubuntu-latest
env:
#Variable for the name of the branch to cherry-pick into.
#It will remain 'invalid' if no branch is specified
destination_branch: 'invalid'
#Name of the autogenerated branch to create the PR from
auto_branch: 'auto-${{github.event.after}}'
#Username for the cherrypick
user_name: "Dynamo-Bot"
steps:
- name: checkout
uses: actions/checkout@v3
#Removes posible conflicting characters on the commit message
#This is because the content of the message will be passed to a script as a parameter and quotation marks will split the text as if it where multiple parameters.
- name: Remove conflicting chars
uses: frabert/replace-string-action@v1.2
id: remove_quotations
with:
pattern: "\""
string: ${{github.event.commits[0].message}}
replace-with: "-"
flags: g
#Checks the message looking for a cherry-pick request and extracts the target branch name
- name: Check Information
env:
ISSUE_BODY_PARSED: ${{steps.remove_quotations.outputs.replaced}}
id: check-info
run: |
echo "destination_branch=$(pwsh .\\.github\\scripts\\cherry_pick_check.ps1 "${{ env.ISSUE_BODY_PARSED }}" )" >> $GITHUB_ENV
#If a target branch was found will run the action
- if: env.destination_branch != 'invalid'
name: Create PR to branch
run: |
git config user.name "${{env.user_name}}"
git fetch --all
git checkout -b ${{env.auto_branch}} origin/${{env.destination_branch}}
git cherry-pick -x ${{github.event.after}} --strategy-option theirs
git push -u origin ${{env.auto_branch}}
hub pull-request -b "${{env.destination_branch}}" -h "${{env.auto_branch}}" -m "${{env.pr_message}}"
env:
#Token used for the pull request. Corresponds to the DynamoBot account
GITHUB_TOKEN: ${{secrets.DYNAMOBOTTOKEN}}
ISSUE_BODY_PARSED: ${{steps.remove_quotations.outputs.replaced}}
#This represents the title and description of the pr in Markdown format
#Everything before the first blank line will be the title
#Everything after will be included in the description
pr_message: |
Cherry-Pick from commit: ${{github.event.after}}
### Cherry-picking:
[Commit](https://github.com/DynamoDS/Dynamo/commit/${{github.event.after}})
### Pull request:
${{ env.ISSUE_BODY_PARSED }}