Here’s a module that will allow you to save a project milestone for any project on the current Iguana instance.
Note: This module will not work if the target project exists on a different Iguana instance.
local translator = {} function node.getChannel(Config, Name) for i=1,#Config.iguana_config.channel_config do local Channel = Config.iguana_config.channel_config[i] if Channel.name:nodeValue() == Name then return Channel end end return nil end function node.S(ANode) return tostring(ANode) end function Split(s, d) local t = {} local i = 0 local f local match = '(.-)' .. d .. '()' if string.find(s, d) == nil then return {s} end for sub, j in string.gfind(s, match) do i = i + 1 t[i] = sub f = j end if i~= 0 then t[i+1]=string.sub(s,f) end return t end local function GetSandbox(Root, WorkingDirectory) os.execute('mkdir "'..Root..'"') os.execute('cd "'..Root..'" & "'..WorkingDirectory..'fossil" open "'..WorkingDirectory..'vcs_repo.sqlite"') end local function CheckGuidArguments(T) if not T.channel then error('Parameter 'channel' is required.', 3) elseif not T.component_type then error('Parameter 'component_type' is required.', 3) end end local function CheckSaveMilestoneArguments(T) if not T.text then error('Parameter 'text' is required.', 3) elseif not T.guid then error('Parameter 'guid' is required.', 3) elseif not T.url then error('Parameter 'url' is required.', 3) elseif not T.user then error('Parameter 'user' is required.', 3) elseif not T.password then error('Parameter 'password' is required.', 3) end end local function ScriptGuid(ScriptType, ChannelName, Config) local Channel = Config:getChannel(ChannelName) if not Channel then error('Channel '..ChannelName..' does not exist', 3) end if ScriptType == translator.TO then local Component = Channel.to_mapper if not Component then error('There is no "To Translator" component for this channel', 3) end return Component.guid:nodeValue() end if ScriptType == translator.FROM then local Component = Channel.from_mapper if not Component then error('There is no "From Translator" component for this channel', 3) end return Component.guid:nodeValue() end if ScriptType == translator.FILTER then local Component= Channel.message_filter if not Component then error('There is no "Translator Filter" component for this channel', 3) end return Component.translator_guid:nodeValue() end if ScriptType == translator.ACK then local Component = Channel.from_llp_listener if not Component or not Component.ack_script then error('There is no "Custom ACK Translator" component for this channel', 3) end return Component.ack_script:nodeValue() end if ScriptType == translator.HTTPS then local Component = Channel.from_http if not Component or not Component.from_http_guid then error('There is no "From HTTPS translator" component for this channel', 3) end return Channel.from_http.guid:nodeValue() end end --[[ Function takes user credentials and returns a valid session id upon a successful login. ]] local function GetLoginKey(Url, User, Password) local Success, Result, _, Headers = pcall( net.http.get, { url=Url..'login.html', parameters={ username=User, password=Password }, live=true } ) if not Success then return nil, Result end -- That gives us our session cookie which we use for our -- login credentials. The login interface was not quite -- meant for an API - but the problem is solvable. local SessionId = Headers["Set-Cookie"] if not SessionId then error('Username and/or password wrong',3) end return Split(SessionId,' ')[1] end --[[ Function returns the dependency list of the Translator project identified by the inputted GUID. ]] local function GetDependencies(Guid, User, WorkingDirectory) local PathSeparator = WorkingDirectory:sub(#WorkingDirectory) local Sandbox = 'edit'..PathSeparator..User..PathSeparator local Project = Sandbox..Guid..PathSeparator..'project.prj' local ProjectFile = io.open(Project, 'r') -- The user's sandbox may not yet exist. If not, let's create it. if not ProjectFile then GetSandbox(Sandbox, WorkingDirectory) ProjectFile = io.open(Project, 'r') end local ProjectInfo = json.parse{data=ProjectFile:read('*a')} local Dependencies = ProjectInfo.LuaDependencies local Size = #Dependencies for k,v in pairs(ProjectInfo.OtherDependencies) do Dependencies[Size + k] = v end io.close(ProjectFile) return Dependencies end --[[ Translator interface ]] translator.FROM = 'from' translator.TO = 'to' translator.FILTER = 'filter' translator.ACK = 'ack' translator.HTTPS = 'https' --[[ Function returns the GUID associated the Translator project identified by the inputted channel name and component type. ]] function translator.guid(T) CheckGuidArguments(T) local ChannelName = T.channel local ComponentType = T.component_type -- Read the config file. local ConfigFile = io.open('IguanaConfiguration.xml', 'r') Config = xml.parse{data=ConfigFile:read('*a')} io.close(ConfigFile) return ScriptGuid(ComponentType, ChannelName, Config) end local GuidHelpData = { Title='translator.guid', Usage=[[translator.guid{channel=<value>, component_type=<value>}]], Desc=[[Returns the GUID associated with the Translator project identified by the inputted channel name and component type.]], Returns='The GUID of interest.', ParameterTable=true, Parameters={ {channel={Desc='The channel name containing the Translator project.'}}, {component_type={Desc='The component type in which the Translator project is defined.'}} }, Examples={ [[translator.guid{channel='Example', component_type=translator.FROM}]] }, SeeAlso=nil } help.set{input_function=translator.guid, help_data=GuidHelpData} --[[ Function commits the project identified by the inputted GUID under the given milestone name. ]] function translator.saveMilestone(T) CheckSaveMilestoneArguments(T) local Text = T.text local Guid = T.guid local Url = T.url local User = T.user local Password = T.password local Live = T.live or not iguana.isTest() local LoginKey, LoginResult = GetLoginKey(Url, User, Password) if not LoginKey then error(LoginResult, 2) end local WorkingDirectory = iguana.workingDir() local Dependencies = GetDependencies(Guid, User, WorkingDirectory) local DependencyString = 'mainnproject settingsn'..table.concat(Dependencies, 'n') if not Live then return 'Set live=true to really run the code' end local Success, Result = pcall( net.http.post, { url=Url..'source_control', parameters={ RequestType='save_milestone', FileLabels=DependencyString, MilestoneName=Text, ChannelGuid=Guid }, headers={Cookie=LoginKey}, live=Live } ) if not Success then error(Result, 2) end Success, Result = pcall(json.parse,{data=Result}) if not Success then error(Result, 2) elseif Result.ErrorMessage then error(Result.ErrorMessage, 2) elseif Result.PermissionIssue then error(Result.PermissionIssue, 2) end return "Saved milestone "..T.text end local SaveHelpData = { Title='translator.saveMilestone', Usage=[[translator.saveMilestone{text=<value>, guid=<value>, url=<value>, user=<value>, password=<value>, live=<value>}]], Desc=[[Commits the Translator project associated with the inputted GUID.<br><br>Important Note: This API can only save milestones of projects that exist on the same instance of Iguana that uses this API.]], Returns=nil, ParameterTable=true, Parameters={ {text={Desc='The milestone name to use for the commit.'}}, {guid={Desc='The GUID associated with the project being committed.'}}, {url={Desc=[[The URL of the Iguana server running the project that uses this API.]]}}, {user={Desc='User name to login with.'}}, {password={Desc='Password to login with.'}}, {live={Desc='Flag that determines if the code will be run.'}} }, Examples={ [[translator.saveMilestone{ text='Milestone 1', guid='123456', url='http://localhost:6543/', user='admin', password='password', live=true }]] }, SeeAlso=nil } help.set{input_function=translator.saveMilestone, help_data=SaveHelpData} return translator
Here’s a main module that uses the module above.
translator = require 'translator' function main() translator.saveMilestone{ text='New milestone at '..os.date('%Y%m%d %H:%M:%S'), guid=translator.guid{ channel='XDS.b RET', component_type=translator.FROM }, url='http://10.211.55.8:6543/', user='admin', password='password', live=true } end