Skip to content

[Manual Test] {{ test_id }} by {{ user_name }} #60

[Manual Test] {{ test_id }} by {{ user_name }}

[Manual Test] {{ test_id }} by {{ user_name }} #60

Workflow file for this run

name: Manual Test Report
on:
issues:
types: [opened, edited]
permissions:
contents: read
issues: write
pull-requests: write
jobs:
process-manual-test:
if: contains(github.event.issue.title, '[Manual Test]')
runs-on: ubuntu-latest
steps:
# ──────────────────────────────────────────────────────────────────────
# 1. Check out repo so templates are available
# ──────────────────────────────────────────────────────────────────────
- name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 1
# ──────────────────────────────────────────────────────────────────────
# 2. Parse the Issue‑Form data
# – we point the parser *into* the ISSUE_TEMPLATE directory
# ──────────────────────────────────────────────────────────────────────
- name: Parse issue form
id: parse
uses: issue-ops/[email protected]
with:
body: ${{ github.event.issue.body }}
# "manual-test-report.yml" lives inside .github/ISSUE_TEMPLATE
issue-form-template: manual-test-report.yml
# ──────────────────────────────────────────────────────────────────────
# 3. Build a simple field map for later steps
# ──────────────────────────────────────────────────────────────────────
- name: Build field set
id: build
shell: bash
run: |
{
echo "test_id=${{ steps.parse.outputs.numeric_test_id }}"
echo "estimate=${{ steps.parse.outputs.estimate_text }}"
echo "lv_version=${{ steps.parse.outputs.labview_version }}"
echo "bitness=${{ steps.parse.outputs.labview_bitness }}"
echo "os_used=${{ steps.parse.outputs.os_used }}"
echo "test_result=${{ steps.parse.outputs.test_result }}"
echo "notes=${{ steps.parse.outputs.notes }}"
} >> "$GITHUB_OUTPUT"
# ──────────────────────────────────────────────────────────────────────
# 4. Update / create fields in organisation project 29
# (unchanged from the previous working file)
# ──────────────────────────────────────────────────────────────────────
- name: Update project fields
uses: actions/github-script@v6
env:
ORG_LOGIN: ni
PROJ_NUMBER: 29
TEST_ID: ${{ steps.build.outputs.test_id }}
ESTIMATE: ${{ steps.build.outputs.estimate }}
LV_VERSION: ${{ steps.build.outputs.lv_version }}
BITNESS: ${{ steps.build.outputs.bitness }}
OS_USED: ${{ steps.build.outputs.os_used }}
TEST_RESULT: ${{ steps.build.outputs.test_result }}
NOTES: ${{ steps.build.outputs.notes }}
with:
github-token: ${{ secrets.PROJECTS_PAT }}
script: |
/* ──────────────────────────────────────────────────────────────
GitHub‑Script: create the project item (if missing), ensure
every custom field exists, autogenerate select options, and
then write the values. Detailed logging remains enabled so
you can trace each API call from the Actions log.
─────────────────────────────────────────────────────────── */
const orgLogin = process.env.ORG_LOGIN;
const projectNumber = parseInt(process.env.PROJ_NUMBER,10);
const contentId = context.payload.issue.node_id;
const log = (m)=>core.info(` ${m}`);
const warn = (m)=>core.warning(` ${m}`);
// 1) Locate the project
log(`🔍 Looking up Project #${projectNumber} in org “${orgLogin}”`);
const pj = await github.graphql(`
query($org:String!,$num:Int!){
organization(login:$org){
projectV2(number:$num){ id title }
}
}`, {org:orgLogin, num:projectNumber});
const project = pj.organization.projectV2;
if(!project) core.setFailed(`Project #${projectNumber} not found.`);
log(`➡️ Using project “${project.title}”`); const projectId = project.id;
// 2) Ensure an item exists for this issue
async function ensureItem(){
const res = await github.graphql(`
query($pid:ID!,$cid:ID!){
node(id:$pid){
... on ProjectV2{
items(first:1,filterBy:{contentId:$cid}){
nodes{ id }
}
}
}
}`, {pid:projectId,cid:contentId});
const found = res.node.items.nodes[0];
if(found){ log(`ℹ️ Found item ${found.id}`); return found.id; }
log('➕ Adding issue to project…');
const add = await github.graphql(`
mutation($pid:ID!,$cid:ID!){
addProjectV2ItemById(input:{projectId:$pid,contentId:$cid}){
item{id}
}
}`, {pid:projectId,cid:contentId});
return add.addProjectV2ItemById.item.id;
}
// 3) Fetch / create fields
async function fetchFields(){
const res = await github.graphql(`
query($pid:ID!){
node(id:$pid){
... on ProjectV2{
fields(first:100){
nodes{
__typename
... on ProjectV2FieldCommon { id name dataType }
... on ProjectV2SingleSelectField {
id name dataType
options { id name }
}
}
}
}
}
}`, {pid:projectId});
return res.node.fields.nodes;
}
async function createField(name,type){
log(`⚙️ Creating field “${name}”`);
const res = await github.graphql(`
mutation($pid:ID!,$name:String!,$type:ProjectV2CustomFieldDataType!){
createProjectV2Field(input:{
projectId:$pid, name:$name, dataType:$type,
${type==='SINGLE_SELECT'
? 'singleSelectOptions:[{name:"Passed"},{name:"Failed"},{name:"Needs Review"}]'
: ''}
}){
field{
__typename
... on ProjectV2FieldCommon { id name dataType }
... on ProjectV2SingleSelectField {
id name dataType
options { id name }
}
}
}
}`, {pid:projectId, name, type});
return res.createProjectV2Field.field;
}
async function ensureOption(field,optName){
if(field.dataType!=='SINGLE_SELECT') return null;
const hit = field.options.find(o=>o.name===optName);
if(hit) return hit.id;
log(`⚙️ Adding option “${optName}”`);
const res = await github.graphql(`
mutation($pid:ID!,$fid:ID!,$name:String!){
createProjectV2SingleSelectFieldOption(input:{
projectId:$pid, fieldId:$fid, name:$name
}){
option{id}
}
}`, {pid:projectId,fid:field.id,name:optName});
return res.createProjectV2SingleSelectFieldOption.option.id;
}
async function setField(itemId,field,val){
let payload;
if(field.dataType==='SINGLE_SELECT'){
const optId = await ensureOption(field,val);
payload = {singleSelectOptionId:optId};
}else{
payload = {text:val};
}
await github.graphql(`
mutation($pid:ID!,$iid:ID!,$fid:ID!,$val:ProjectV2FieldValue!){
updateProjectV2ItemFieldValue(input:{
projectId:$pid,itemId:$iid,fieldId:$fid,value:$val
}){ projectV2Item{id} }
}`, {pid:projectId,iid:itemId,fid:field.id,val:payload});
log(`✅ “${field.name}” → “${val}”`);
}
// 4) Execute
const itemId = await ensureItem();
let fields = await fetchFields();
const wanted = [
{n:'TestID', v:process.env.TEST_ID, t:'TEXT'},
{n:'Estimate', v:process.env.ESTIMATE, t:'TEXT'},
{n:'Operating System', v:process.env.OS_USED, t:'TEXT'},
{n:'LabVIEW Version', v:process.env.LV_VERSION, t:'TEXT'},
{n:'LabVIEW Bitness', v:process.env.BITNESS, t:'TEXT'},
{n:'Notes', v:process.env.NOTES, t:'TEXT'},
{n:'Test Result', v:process.env.TEST_RESULT,t:'SINGLE_SELECT'},
];
log('✏️ Updating project fields');
for(const f of wanted){
if(!f.v){ warn(`Skipping “${f.n}” – empty`); continue; }
let fld = fields.find(x=>x.name===f.n);
if(!fld){ fld = await createField(f.n,f.t); fields.push(fld); }
await setField(itemId,fld,f.v);
}
log('🎉 Done');